@proseql/core 0.1.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/LICENSE +21 -0
- package/dist/errors/crud-errors.d.ts +98 -0
- package/dist/errors/crud-errors.d.ts.map +1 -0
- package/dist/errors/crud-errors.js +23 -0
- package/dist/errors/crud-errors.js.map +1 -0
- package/dist/errors/index.d.ts +16 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +12 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/errors/migration-errors.d.ts +22 -0
- package/dist/errors/migration-errors.d.ts.map +1 -0
- package/dist/errors/migration-errors.js +14 -0
- package/dist/errors/migration-errors.js.map +1 -0
- package/dist/errors/plugin-errors.d.ts +15 -0
- package/dist/errors/plugin-errors.d.ts.map +1 -0
- package/dist/errors/plugin-errors.js +11 -0
- package/dist/errors/plugin-errors.js.map +1 -0
- package/dist/errors/query-errors.d.ts +31 -0
- package/dist/errors/query-errors.d.ts.map +1 -0
- package/dist/errors/query-errors.js +11 -0
- package/dist/errors/query-errors.js.map +1 -0
- package/dist/errors/storage-errors.d.ts +30 -0
- package/dist/errors/storage-errors.d.ts.map +1 -0
- package/dist/errors/storage-errors.js +11 -0
- package/dist/errors/storage-errors.js.map +1 -0
- package/dist/factories/crud-factory-with-relationships.d.ts +28 -0
- package/dist/factories/crud-factory-with-relationships.d.ts.map +1 -0
- package/dist/factories/crud-factory-with-relationships.js +8 -0
- package/dist/factories/crud-factory-with-relationships.js.map +1 -0
- package/dist/factories/crud-factory.d.ts +25 -0
- package/dist/factories/crud-factory.d.ts.map +1 -0
- package/dist/factories/crud-factory.js +8 -0
- package/dist/factories/crud-factory.js.map +1 -0
- package/dist/factories/database-effect.d.ts +241 -0
- package/dist/factories/database-effect.d.ts.map +1 -0
- package/dist/factories/database-effect.js +859 -0
- package/dist/factories/database-effect.js.map +1 -0
- package/dist/hooks/hook-runner.d.ts +60 -0
- package/dist/hooks/hook-runner.d.ts.map +1 -0
- package/dist/hooks/hook-runner.js +107 -0
- package/dist/hooks/hook-runner.js.map +1 -0
- package/dist/index.d.ts +84 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +110 -0
- package/dist/index.js.map +1 -0
- package/dist/indexes/index-lookup.d.ts +33 -0
- package/dist/indexes/index-lookup.d.ts.map +1 -0
- package/dist/indexes/index-lookup.js +180 -0
- package/dist/indexes/index-lookup.js.map +1 -0
- package/dist/indexes/index-manager.d.ts +118 -0
- package/dist/indexes/index-manager.d.ts.map +1 -0
- package/dist/indexes/index-manager.js +345 -0
- package/dist/indexes/index-manager.js.map +1 -0
- package/dist/indexes/search-index.d.ts +179 -0
- package/dist/indexes/search-index.d.ts.map +1 -0
- package/dist/indexes/search-index.js +405 -0
- package/dist/indexes/search-index.js.map +1 -0
- package/dist/migrations/migration-runner.d.ts +70 -0
- package/dist/migrations/migration-runner.d.ts.map +1 -0
- package/dist/migrations/migration-runner.js +271 -0
- package/dist/migrations/migration-runner.js.map +1 -0
- package/dist/migrations/migration-types.d.ts +63 -0
- package/dist/migrations/migration-types.d.ts.map +1 -0
- package/dist/migrations/migration-types.js +5 -0
- package/dist/migrations/migration-types.js.map +1 -0
- package/dist/operations/crud/create-with-relationships.d.ts +44 -0
- package/dist/operations/crud/create-with-relationships.d.ts.map +1 -0
- package/dist/operations/crud/create-with-relationships.js +483 -0
- package/dist/operations/crud/create-with-relationships.js.map +1 -0
- package/dist/operations/crud/create.d.ts +48 -0
- package/dist/operations/crud/create.d.ts.map +1 -0
- package/dist/operations/crud/create.js +333 -0
- package/dist/operations/crud/create.js.map +1 -0
- package/dist/operations/crud/delete-with-relationships.d.ts +63 -0
- package/dist/operations/crud/delete-with-relationships.d.ts.map +1 -0
- package/dist/operations/crud/delete-with-relationships.js +395 -0
- package/dist/operations/crud/delete-with-relationships.js.map +1 -0
- package/dist/operations/crud/delete.d.ts +58 -0
- package/dist/operations/crud/delete.d.ts.map +1 -0
- package/dist/operations/crud/delete.js +267 -0
- package/dist/operations/crud/delete.js.map +1 -0
- package/dist/operations/crud/unique-check.d.ts +114 -0
- package/dist/operations/crud/unique-check.d.ts.map +1 -0
- package/dist/operations/crud/unique-check.js +383 -0
- package/dist/operations/crud/unique-check.js.map +1 -0
- package/dist/operations/crud/update-with-relationships.d.ts +45 -0
- package/dist/operations/crud/update-with-relationships.d.ts.map +1 -0
- package/dist/operations/crud/update-with-relationships.js +516 -0
- package/dist/operations/crud/update-with-relationships.js.map +1 -0
- package/dist/operations/crud/update.d.ts +91 -0
- package/dist/operations/crud/update.d.ts.map +1 -0
- package/dist/operations/crud/update.js +505 -0
- package/dist/operations/crud/update.js.map +1 -0
- package/dist/operations/crud/upsert.d.ts +52 -0
- package/dist/operations/crud/upsert.d.ts.map +1 -0
- package/dist/operations/crud/upsert.js +386 -0
- package/dist/operations/crud/upsert.js.map +1 -0
- package/dist/operations/query/aggregate.d.ts +30 -0
- package/dist/operations/query/aggregate.d.ts.map +1 -0
- package/dist/operations/query/aggregate.js +227 -0
- package/dist/operations/query/aggregate.js.map +1 -0
- package/dist/operations/query/cursor-stream.d.ts +18 -0
- package/dist/operations/query/cursor-stream.d.ts.map +1 -0
- package/dist/operations/query/cursor-stream.js +199 -0
- package/dist/operations/query/cursor-stream.js.map +1 -0
- package/dist/operations/query/filter-stream.d.ts +12 -0
- package/dist/operations/query/filter-stream.d.ts.map +1 -0
- package/dist/operations/query/filter-stream.js +167 -0
- package/dist/operations/query/filter-stream.js.map +1 -0
- package/dist/operations/query/filter.d.ts +13 -0
- package/dist/operations/query/filter.d.ts.map +1 -0
- package/dist/operations/query/filter.js +267 -0
- package/dist/operations/query/filter.js.map +1 -0
- package/dist/operations/query/paginate-stream.d.ts +11 -0
- package/dist/operations/query/paginate-stream.d.ts.map +1 -0
- package/dist/operations/query/paginate-stream.js +22 -0
- package/dist/operations/query/paginate-stream.js.map +1 -0
- package/dist/operations/query/query-helpers.d.ts +14 -0
- package/dist/operations/query/query-helpers.d.ts.map +1 -0
- package/dist/operations/query/query-helpers.js +22 -0
- package/dist/operations/query/query-helpers.js.map +1 -0
- package/dist/operations/query/resolve-computed.d.ts +142 -0
- package/dist/operations/query/resolve-computed.d.ts.map +1 -0
- package/dist/operations/query/resolve-computed.js +197 -0
- package/dist/operations/query/resolve-computed.js.map +1 -0
- package/dist/operations/query/search.d.ts +110 -0
- package/dist/operations/query/search.d.ts.map +1 -0
- package/dist/operations/query/search.js +188 -0
- package/dist/operations/query/search.js.map +1 -0
- package/dist/operations/query/select-stream.d.ts +27 -0
- package/dist/operations/query/select-stream.d.ts.map +1 -0
- package/dist/operations/query/select-stream.js +88 -0
- package/dist/operations/query/select-stream.js.map +1 -0
- package/dist/operations/query/select.d.ts +54 -0
- package/dist/operations/query/select.d.ts.map +1 -0
- package/dist/operations/query/select.js +159 -0
- package/dist/operations/query/select.js.map +1 -0
- package/dist/operations/query/sort-stream.d.ts +46 -0
- package/dist/operations/query/sort-stream.d.ts.map +1 -0
- package/dist/operations/query/sort-stream.js +158 -0
- package/dist/operations/query/sort-stream.js.map +1 -0
- package/dist/operations/query/sort.d.ts +9 -0
- package/dist/operations/query/sort.d.ts.map +1 -0
- package/dist/operations/query/sort.js +58 -0
- package/dist/operations/query/sort.js.map +1 -0
- package/dist/operations/relationships/populate-stream.d.ts +29 -0
- package/dist/operations/relationships/populate-stream.d.ts.map +1 -0
- package/dist/operations/relationships/populate-stream.js +159 -0
- package/dist/operations/relationships/populate-stream.js.map +1 -0
- package/dist/operations/relationships/populate.d.ts +15 -0
- package/dist/operations/relationships/populate.d.ts.map +1 -0
- package/dist/operations/relationships/populate.js +228 -0
- package/dist/operations/relationships/populate.js.map +1 -0
- package/dist/plugins/plugin-hooks.d.ts +25 -0
- package/dist/plugins/plugin-hooks.d.ts.map +1 -0
- package/dist/plugins/plugin-hooks.js +64 -0
- package/dist/plugins/plugin-hooks.js.map +1 -0
- package/dist/plugins/plugin-registry.d.ts +26 -0
- package/dist/plugins/plugin-registry.d.ts.map +1 -0
- package/dist/plugins/plugin-registry.js +150 -0
- package/dist/plugins/plugin-registry.js.map +1 -0
- package/dist/plugins/plugin-types.d.ts +95 -0
- package/dist/plugins/plugin-types.d.ts.map +1 -0
- package/dist/plugins/plugin-types.js +6 -0
- package/dist/plugins/plugin-types.js.map +1 -0
- package/dist/plugins/plugin-validation.d.ts +49 -0
- package/dist/plugins/plugin-validation.d.ts.map +1 -0
- package/dist/plugins/plugin-validation.js +295 -0
- package/dist/plugins/plugin-validation.js.map +1 -0
- package/dist/reactive/change-event.d.ts +44 -0
- package/dist/reactive/change-event.d.ts.map +1 -0
- package/dist/reactive/change-event.js +49 -0
- package/dist/reactive/change-event.js.map +1 -0
- package/dist/reactive/change-pubsub.d.ts +32 -0
- package/dist/reactive/change-pubsub.d.ts.map +1 -0
- package/dist/reactive/change-pubsub.js +31 -0
- package/dist/reactive/change-pubsub.js.map +1 -0
- package/dist/reactive/evaluate-query.d.ts +62 -0
- package/dist/reactive/evaluate-query.d.ts.map +1 -0
- package/dist/reactive/evaluate-query.js +57 -0
- package/dist/reactive/evaluate-query.js.map +1 -0
- package/dist/reactive/watch-by-id.d.ts +53 -0
- package/dist/reactive/watch-by-id.d.ts.map +1 -0
- package/dist/reactive/watch-by-id.js +55 -0
- package/dist/reactive/watch-by-id.js.map +1 -0
- package/dist/reactive/watch.d.ts +78 -0
- package/dist/reactive/watch.d.ts.map +1 -0
- package/dist/reactive/watch.js +133 -0
- package/dist/reactive/watch.js.map +1 -0
- package/dist/serializers/codecs/hjson.d.ts +33 -0
- package/dist/serializers/codecs/hjson.d.ts.map +1 -0
- package/dist/serializers/codecs/hjson.js +40 -0
- package/dist/serializers/codecs/hjson.js.map +1 -0
- package/dist/serializers/codecs/json.d.ts +22 -0
- package/dist/serializers/codecs/json.d.ts.map +1 -0
- package/dist/serializers/codecs/json.js +28 -0
- package/dist/serializers/codecs/json.js.map +1 -0
- package/dist/serializers/codecs/json5.d.ts +26 -0
- package/dist/serializers/codecs/json5.d.ts.map +1 -0
- package/dist/serializers/codecs/json5.js +33 -0
- package/dist/serializers/codecs/json5.js.map +1 -0
- package/dist/serializers/codecs/jsonc.d.ts +29 -0
- package/dist/serializers/codecs/jsonc.d.ts.map +1 -0
- package/dist/serializers/codecs/jsonc.js +38 -0
- package/dist/serializers/codecs/jsonc.js.map +1 -0
- package/dist/serializers/codecs/jsonl.d.ts +17 -0
- package/dist/serializers/codecs/jsonl.d.ts.map +1 -0
- package/dist/serializers/codecs/jsonl.js +31 -0
- package/dist/serializers/codecs/jsonl.js.map +1 -0
- package/dist/serializers/codecs/prose.d.ts +419 -0
- package/dist/serializers/codecs/prose.d.ts.map +1 -0
- package/dist/serializers/codecs/prose.js +1060 -0
- package/dist/serializers/codecs/prose.js.map +1 -0
- package/dist/serializers/codecs/toml.d.ts +23 -0
- package/dist/serializers/codecs/toml.d.ts.map +1 -0
- package/dist/serializers/codecs/toml.js +66 -0
- package/dist/serializers/codecs/toml.js.map +1 -0
- package/dist/serializers/codecs/toon.d.ts +20 -0
- package/dist/serializers/codecs/toon.d.ts.map +1 -0
- package/dist/serializers/codecs/toon.js +33 -0
- package/dist/serializers/codecs/toon.js.map +1 -0
- package/dist/serializers/codecs/yaml.d.ts +24 -0
- package/dist/serializers/codecs/yaml.d.ts.map +1 -0
- package/dist/serializers/codecs/yaml.js +31 -0
- package/dist/serializers/codecs/yaml.js.map +1 -0
- package/dist/serializers/format-codec.d.ts +53 -0
- package/dist/serializers/format-codec.d.ts.map +1 -0
- package/dist/serializers/format-codec.js +148 -0
- package/dist/serializers/format-codec.js.map +1 -0
- package/dist/serializers/presets.d.ts +48 -0
- package/dist/serializers/presets.d.ts.map +1 -0
- package/dist/serializers/presets.js +72 -0
- package/dist/serializers/presets.js.map +1 -0
- package/dist/serializers/serializer-service.d.ts +11 -0
- package/dist/serializers/serializer-service.d.ts.map +1 -0
- package/dist/serializers/serializer-service.js +4 -0
- package/dist/serializers/serializer-service.js.map +1 -0
- package/dist/state/collection-state.d.ts +19 -0
- package/dist/state/collection-state.d.ts.map +1 -0
- package/dist/state/collection-state.js +15 -0
- package/dist/state/collection-state.js.map +1 -0
- package/dist/state/state-operations.d.ts +38 -0
- package/dist/state/state-operations.d.ts.map +1 -0
- package/dist/state/state-operations.js +65 -0
- package/dist/state/state-operations.js.map +1 -0
- package/dist/storage/in-memory-adapter-layer.d.ts +16 -0
- package/dist/storage/in-memory-adapter-layer.d.ts.map +1 -0
- package/dist/storage/in-memory-adapter-layer.js +81 -0
- package/dist/storage/in-memory-adapter-layer.js.map +1 -0
- package/dist/storage/persistence-effect.d.ts +244 -0
- package/dist/storage/persistence-effect.d.ts.map +1 -0
- package/dist/storage/persistence-effect.js +551 -0
- package/dist/storage/persistence-effect.js.map +1 -0
- package/dist/storage/storage-service.d.ts +22 -0
- package/dist/storage/storage-service.d.ts.map +1 -0
- package/dist/storage/storage-service.js +4 -0
- package/dist/storage/storage-service.js.map +1 -0
- package/dist/storage/transforms.d.ts +183 -0
- package/dist/storage/transforms.d.ts.map +1 -0
- package/dist/storage/transforms.js +263 -0
- package/dist/storage/transforms.js.map +1 -0
- package/dist/transactions/transaction.d.ts +87 -0
- package/dist/transactions/transaction.d.ts.map +1 -0
- package/dist/transactions/transaction.js +240 -0
- package/dist/transactions/transaction.js.map +1 -0
- package/dist/types/aggregate-types.d.ts +73 -0
- package/dist/types/aggregate-types.d.ts.map +1 -0
- package/dist/types/aggregate-types.js +14 -0
- package/dist/types/aggregate-types.js.map +1 -0
- package/dist/types/computed-types.d.ts +71 -0
- package/dist/types/computed-types.d.ts.map +1 -0
- package/dist/types/computed-types.js +8 -0
- package/dist/types/computed-types.js.map +1 -0
- package/dist/types/crud-relationship-types.d.ts +180 -0
- package/dist/types/crud-relationship-types.d.ts.map +1 -0
- package/dist/types/crud-relationship-types.js +17 -0
- package/dist/types/crud-relationship-types.js.map +1 -0
- package/dist/types/crud-types.d.ts +343 -0
- package/dist/types/crud-types.d.ts.map +1 -0
- package/dist/types/crud-types.js +43 -0
- package/dist/types/crud-types.js.map +1 -0
- package/dist/types/cursor-types.d.ts +52 -0
- package/dist/types/cursor-types.d.ts.map +1 -0
- package/dist/types/cursor-types.js +2 -0
- package/dist/types/cursor-types.js.map +1 -0
- package/dist/types/database-config-types.d.ts +196 -0
- package/dist/types/database-config-types.d.ts.map +1 -0
- package/dist/types/database-config-types.js +11 -0
- package/dist/types/database-config-types.js.map +1 -0
- package/dist/types/hook-types.d.ts +158 -0
- package/dist/types/hook-types.d.ts.map +1 -0
- package/dist/types/hook-types.js +6 -0
- package/dist/types/hook-types.js.map +1 -0
- package/dist/types/index-types.d.ts +42 -0
- package/dist/types/index-types.d.ts.map +1 -0
- package/dist/types/index-types.js +8 -0
- package/dist/types/index-types.js.map +1 -0
- package/dist/types/operators.d.ts +5 -0
- package/dist/types/operators.d.ts.map +1 -0
- package/dist/types/operators.js +297 -0
- package/dist/types/operators.js.map +1 -0
- package/dist/types/query-overloads.d.ts +54 -0
- package/dist/types/query-overloads.d.ts.map +1 -0
- package/dist/types/query-overloads.js +3 -0
- package/dist/types/query-overloads.js.map +1 -0
- package/dist/types/reactive-types.d.ts +75 -0
- package/dist/types/reactive-types.d.ts.map +1 -0
- package/dist/types/reactive-types.js +7 -0
- package/dist/types/reactive-types.js.map +1 -0
- package/dist/types/schema-types.d.ts +56 -0
- package/dist/types/schema-types.d.ts.map +1 -0
- package/dist/types/schema-types.js +8 -0
- package/dist/types/schema-types.js.map +1 -0
- package/dist/types/search-types.d.ts +82 -0
- package/dist/types/search-types.d.ts.map +1 -0
- package/dist/types/search-types.js +110 -0
- package/dist/types/search-types.js.map +1 -0
- package/dist/types/types.d.ts +286 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +2 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utils/id-generator.d.ts +97 -0
- package/dist/utils/id-generator.d.ts.map +1 -0
- package/dist/utils/id-generator.js +247 -0
- package/dist/utils/id-generator.js.map +1 -0
- package/dist/utils/nested-path.d.ts +56 -0
- package/dist/utils/nested-path.d.ts.map +1 -0
- package/dist/utils/nested-path.js +119 -0
- package/dist/utils/nested-path.js.map +1 -0
- package/dist/utils/path.d.ts +16 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +24 -0
- package/dist/utils/path.js.map +1 -0
- package/dist/validators/foreign-key.d.ts +49 -0
- package/dist/validators/foreign-key.d.ts.map +1 -0
- package/dist/validators/foreign-key.js +153 -0
- package/dist/validators/foreign-key.js.map +1 -0
- package/dist/validators/schema-validator.d.ts +19 -0
- package/dist/validators/schema-validator.d.ts.map +1 -0
- package/dist/validators/schema-validator.js +34 -0
- package/dist/validators/schema-validator.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effect-based update operations for entities.
|
|
3
|
+
*
|
|
4
|
+
* Uses Ref<ReadonlyMap> for atomic state mutation, Effect Schema for validation,
|
|
5
|
+
* and typed errors (ValidationError, NotFoundError, ForeignKeyError).
|
|
6
|
+
*
|
|
7
|
+
* Preserves all update operators: $increment, $decrement, $multiply,
|
|
8
|
+
* $append, $prepend, $remove, $toggle, $set.
|
|
9
|
+
*/
|
|
10
|
+
import { Effect, PubSub, Ref } from "effect";
|
|
11
|
+
import { NotFoundError, ValidationError, } from "../../errors/crud-errors.js";
|
|
12
|
+
import { runAfterUpdateHooks, runBeforeUpdateHooks, runOnChangeHooks, } from "../../hooks/hook-runner.js";
|
|
13
|
+
import { updateInIndex } from "../../indexes/index-manager.js";
|
|
14
|
+
import { updateInSearchIndex } from "../../indexes/search-index.js";
|
|
15
|
+
import { validateForeignKeysEffect } from "../../validators/foreign-key.js";
|
|
16
|
+
import { validateEntity } from "../../validators/schema-validator.js";
|
|
17
|
+
import { checkUniqueConstraints, } from "./unique-check.js";
|
|
18
|
+
// ============================================================================
|
|
19
|
+
// Update Operators Implementation
|
|
20
|
+
// ============================================================================
|
|
21
|
+
/**
|
|
22
|
+
* Check if an object is a plain object (not null, not an array).
|
|
23
|
+
*/
|
|
24
|
+
function isPlainObject(value) {
|
|
25
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if an object contains any $-prefixed keys (operator object).
|
|
29
|
+
*/
|
|
30
|
+
function hasOperatorKeys(obj) {
|
|
31
|
+
return Object.keys(obj).some((k) => k.startsWith("$"));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Apply update operators to a value.
|
|
35
|
+
* Supports: $increment, $decrement, $multiply (number),
|
|
36
|
+
* $append, $prepend (string/array), $remove (array),
|
|
37
|
+
* $toggle (boolean), $set (all types).
|
|
38
|
+
*/
|
|
39
|
+
function applyOperator(currentValue, operator) {
|
|
40
|
+
// Number operators
|
|
41
|
+
if (typeof currentValue === "number") {
|
|
42
|
+
if ("$increment" in operator && typeof operator.$increment === "number") {
|
|
43
|
+
return (currentValue + operator.$increment);
|
|
44
|
+
}
|
|
45
|
+
if ("$decrement" in operator && typeof operator.$decrement === "number") {
|
|
46
|
+
return (currentValue - operator.$decrement);
|
|
47
|
+
}
|
|
48
|
+
if ("$multiply" in operator && typeof operator.$multiply === "number") {
|
|
49
|
+
return (currentValue * operator.$multiply);
|
|
50
|
+
}
|
|
51
|
+
if ("$set" in operator) {
|
|
52
|
+
return operator.$set;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// String operators
|
|
56
|
+
if (typeof currentValue === "string") {
|
|
57
|
+
if ("$append" in operator && typeof operator.$append === "string") {
|
|
58
|
+
return (currentValue + operator.$append);
|
|
59
|
+
}
|
|
60
|
+
if ("$prepend" in operator && typeof operator.$prepend === "string") {
|
|
61
|
+
return (operator.$prepend + currentValue);
|
|
62
|
+
}
|
|
63
|
+
if ("$set" in operator) {
|
|
64
|
+
return operator.$set;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Array operators
|
|
68
|
+
if (Array.isArray(currentValue)) {
|
|
69
|
+
if ("$append" in operator) {
|
|
70
|
+
const toAppend = Array.isArray(operator.$append)
|
|
71
|
+
? operator.$append
|
|
72
|
+
: [operator.$append];
|
|
73
|
+
return [...currentValue, ...toAppend];
|
|
74
|
+
}
|
|
75
|
+
if ("$prepend" in operator) {
|
|
76
|
+
const toPrepend = Array.isArray(operator.$prepend)
|
|
77
|
+
? operator.$prepend
|
|
78
|
+
: [operator.$prepend];
|
|
79
|
+
return [...toPrepend, ...currentValue];
|
|
80
|
+
}
|
|
81
|
+
if ("$remove" in operator) {
|
|
82
|
+
if (typeof operator.$remove === "function") {
|
|
83
|
+
return currentValue.filter((item) => !operator.$remove(item));
|
|
84
|
+
}
|
|
85
|
+
return currentValue.filter((item) => item !== operator.$remove);
|
|
86
|
+
}
|
|
87
|
+
if ("$set" in operator) {
|
|
88
|
+
return operator.$set;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
// Boolean operators
|
|
92
|
+
if (typeof currentValue === "boolean") {
|
|
93
|
+
if ("$toggle" in operator && operator.$toggle === true) {
|
|
94
|
+
return !currentValue;
|
|
95
|
+
}
|
|
96
|
+
if ("$set" in operator) {
|
|
97
|
+
return operator.$set;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Default: just set the value
|
|
101
|
+
if ("$set" in operator) {
|
|
102
|
+
return operator.$set;
|
|
103
|
+
}
|
|
104
|
+
// If no operator matched, return current value
|
|
105
|
+
return currentValue;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Deep merge an update object into a current object, handling operators at any level.
|
|
109
|
+
*
|
|
110
|
+
* Rules:
|
|
111
|
+
* 1. If update value has $-prefixed keys → it's an operator, apply to current value
|
|
112
|
+
* 2. If update value is a plain object with no $-keys AND current value is also a plain object → recurse
|
|
113
|
+
* 3. Otherwise → direct assignment (replace current value with update value)
|
|
114
|
+
*
|
|
115
|
+
* This allows nested updates like:
|
|
116
|
+
* - `{ metadata: { views: 500 } }` → merges into metadata, preserving other fields
|
|
117
|
+
* - `{ metadata: { views: { $increment: 1 } } }` → applies operator to metadata.views
|
|
118
|
+
* - `{ metadata: { $set: { views: 0 } } }` → replaces entire metadata
|
|
119
|
+
*
|
|
120
|
+
* @param current - The current object to merge into
|
|
121
|
+
* @param updates - The update object containing values and/or operators
|
|
122
|
+
* @returns A new object with updates applied
|
|
123
|
+
*/
|
|
124
|
+
export function deepMergeUpdates(current, updates) {
|
|
125
|
+
const result = { ...current };
|
|
126
|
+
for (const [key, updateValue] of Object.entries(updates)) {
|
|
127
|
+
if (updateValue === undefined) {
|
|
128
|
+
// Skip undefined values
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
const currentValue = current[key];
|
|
132
|
+
if (isPlainObject(updateValue)) {
|
|
133
|
+
if (hasOperatorKeys(updateValue)) {
|
|
134
|
+
// Update value is an operator object → apply operator to current value
|
|
135
|
+
result[key] = applyOperator(currentValue, updateValue);
|
|
136
|
+
}
|
|
137
|
+
else if (isPlainObject(currentValue)) {
|
|
138
|
+
// Both update and current are plain objects with no $ keys → recurse
|
|
139
|
+
result[key] = deepMergeUpdates(currentValue, updateValue);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// Current value is not a plain object → direct assignment
|
|
143
|
+
result[key] = updateValue;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
// Update value is a primitive or array → direct assignment
|
|
148
|
+
result[key] = updateValue;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return result;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Apply update operations to an entity.
|
|
155
|
+
* Handles both direct value assignments and operator objects at any nesting level.
|
|
156
|
+
* Uses deepMergeUpdates for nested object merging with operator support.
|
|
157
|
+
* Automatically sets updatedAt timestamp.
|
|
158
|
+
*/
|
|
159
|
+
export function applyUpdates(entity, updates) {
|
|
160
|
+
const now = new Date().toISOString();
|
|
161
|
+
// Use deepMergeUpdates to handle nested objects and operators at any level
|
|
162
|
+
const merged = deepMergeUpdates(entity, updates);
|
|
163
|
+
// Ensure updatedAt is set
|
|
164
|
+
if (!("updatedAt" in updates)) {
|
|
165
|
+
merged.updatedAt = now;
|
|
166
|
+
}
|
|
167
|
+
return merged;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Validate that an update doesn't violate immutable fields (id, createdAt).
|
|
171
|
+
*/
|
|
172
|
+
export function validateImmutableFields(updates) {
|
|
173
|
+
const immutableFields = ["id", "createdAt"];
|
|
174
|
+
for (const field of immutableFields) {
|
|
175
|
+
if (field in updates) {
|
|
176
|
+
return { valid: false, field };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return { valid: true };
|
|
180
|
+
}
|
|
181
|
+
// ============================================================================
|
|
182
|
+
// Computed Field Stripping
|
|
183
|
+
// ============================================================================
|
|
184
|
+
/**
|
|
185
|
+
* Strip computed field keys from an update input object.
|
|
186
|
+
* Used to remove computed field names from update input before schema validation.
|
|
187
|
+
*
|
|
188
|
+
* @param updates - The update payload (possibly with computed field keys)
|
|
189
|
+
* @param computed - The computed fields configuration that defines which keys to strip
|
|
190
|
+
* @returns A new object with computed field keys removed
|
|
191
|
+
*/
|
|
192
|
+
const stripComputedFromUpdates = (updates, computed) => {
|
|
193
|
+
if (computed === undefined || Object.keys(computed).length === 0) {
|
|
194
|
+
return updates;
|
|
195
|
+
}
|
|
196
|
+
const computedKeys = new Set(Object.keys(computed));
|
|
197
|
+
const result = {};
|
|
198
|
+
for (const key of Object.keys(updates)) {
|
|
199
|
+
if (!computedKeys.has(key)) {
|
|
200
|
+
result[key] = updates[key];
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
};
|
|
205
|
+
// ============================================================================
|
|
206
|
+
// Unique Constraint Helpers
|
|
207
|
+
// ============================================================================
|
|
208
|
+
/**
|
|
209
|
+
* Check if an update operation touches any unique fields.
|
|
210
|
+
*
|
|
211
|
+
* Extracts the update keys (handling $set operators) and checks if any
|
|
212
|
+
* intersect with the fields in the unique constraints.
|
|
213
|
+
*
|
|
214
|
+
* @param updates - The update payload (may contain direct values or operators)
|
|
215
|
+
* @param constraints - Normalized unique constraints
|
|
216
|
+
* @returns True if the update modifies any field that's part of a unique constraint
|
|
217
|
+
*/
|
|
218
|
+
function updateTouchesUniqueFields(updates, constraints) {
|
|
219
|
+
if (constraints.length === 0) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
// Extract the fields being updated
|
|
223
|
+
const updateKeys = new Set();
|
|
224
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
225
|
+
// Check if it's a $set operator
|
|
226
|
+
if (typeof value === "object" &&
|
|
227
|
+
value !== null &&
|
|
228
|
+
!Array.isArray(value) &&
|
|
229
|
+
"$set" in value) {
|
|
230
|
+
updateKeys.add(key);
|
|
231
|
+
}
|
|
232
|
+
else if (value !== undefined) {
|
|
233
|
+
// Direct value assignment or other operators
|
|
234
|
+
updateKeys.add(key);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Check if any update key is in any constraint
|
|
238
|
+
for (const constraintFields of constraints) {
|
|
239
|
+
for (const field of constraintFields) {
|
|
240
|
+
if (updateKeys.has(field)) {
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
// ============================================================================
|
|
248
|
+
// Update Single Entity
|
|
249
|
+
// ============================================================================
|
|
250
|
+
/**
|
|
251
|
+
* Update a single entity by ID with validation, hooks, and foreign key checks.
|
|
252
|
+
*
|
|
253
|
+
* Steps:
|
|
254
|
+
* 1. Validate immutable fields are not being modified
|
|
255
|
+
* 2. Look up entity by ID in Ref state (O(1)) - capture as previous
|
|
256
|
+
* 3. Run beforeUpdate hooks (can transform update payload)
|
|
257
|
+
* 4. Apply update operators to produce new entity
|
|
258
|
+
* 5. Validate through Effect Schema
|
|
259
|
+
* 6. Validate foreign key constraints if relationship fields changed
|
|
260
|
+
* 7. Atomically update in Ref state
|
|
261
|
+
* 8. Update indexes if provided
|
|
262
|
+
*/
|
|
263
|
+
export const update = (collectionName, schema, relationships, ref, stateRefs, indexes, hooks, uniqueFields = [], computed, searchIndexRef, searchIndexFields, changePubSub) => (id, updates) => Effect.gen(function* () {
|
|
264
|
+
// Strip computed field keys from updates (they are derived, not stored)
|
|
265
|
+
const sanitizedUpdates = stripComputedFromUpdates(updates, computed);
|
|
266
|
+
// Validate immutable fields
|
|
267
|
+
const immutableCheck = validateImmutableFields(sanitizedUpdates);
|
|
268
|
+
if (!immutableCheck.valid) {
|
|
269
|
+
const fieldName = immutableCheck.field ?? "unknown";
|
|
270
|
+
return yield* Effect.fail(new ValidationError({
|
|
271
|
+
message: `Cannot update immutable field: ${fieldName}`,
|
|
272
|
+
issues: [
|
|
273
|
+
{
|
|
274
|
+
field: fieldName,
|
|
275
|
+
message: `Cannot update immutable field: ${fieldName}`,
|
|
276
|
+
},
|
|
277
|
+
],
|
|
278
|
+
}));
|
|
279
|
+
}
|
|
280
|
+
// Look up entity by ID (O(1)) - capture as previous for hooks
|
|
281
|
+
const currentMap = yield* Ref.get(ref);
|
|
282
|
+
const previous = currentMap.get(id);
|
|
283
|
+
if (previous === undefined) {
|
|
284
|
+
return yield* Effect.fail(new NotFoundError({
|
|
285
|
+
collection: collectionName,
|
|
286
|
+
id,
|
|
287
|
+
message: `Entity '${id}' not found in collection '${collectionName}'`,
|
|
288
|
+
}));
|
|
289
|
+
}
|
|
290
|
+
// Run beforeUpdate hooks (can transform the update payload)
|
|
291
|
+
const transformedUpdates = yield* runBeforeUpdateHooks(hooks?.beforeUpdate, {
|
|
292
|
+
operation: "update",
|
|
293
|
+
collection: collectionName,
|
|
294
|
+
id,
|
|
295
|
+
existing: previous,
|
|
296
|
+
update: sanitizedUpdates,
|
|
297
|
+
});
|
|
298
|
+
// Apply update operators with (possibly transformed) updates
|
|
299
|
+
const updated = applyUpdates(previous, transformedUpdates);
|
|
300
|
+
// Validate through Effect Schema
|
|
301
|
+
const validated = yield* validateEntity(schema, updated);
|
|
302
|
+
// Validate foreign keys if any relationship fields were updated
|
|
303
|
+
const relationshipFields = Object.keys(relationships).map((field) => relationships[field].foreignKey || `${field}Id`);
|
|
304
|
+
const hasRelationshipUpdate = Object.keys(transformedUpdates).some((key) => relationshipFields.includes(key));
|
|
305
|
+
if (hasRelationshipUpdate) {
|
|
306
|
+
yield* validateForeignKeysEffect(validated, collectionName, relationships, stateRefs);
|
|
307
|
+
}
|
|
308
|
+
// Check unique constraints if the update touches any unique fields
|
|
309
|
+
if (updateTouchesUniqueFields(transformedUpdates, uniqueFields)) {
|
|
310
|
+
yield* checkUniqueConstraints(validated, currentMap, uniqueFields, collectionName);
|
|
311
|
+
}
|
|
312
|
+
// Atomically update in state
|
|
313
|
+
yield* Ref.update(ref, (map) => {
|
|
314
|
+
const next = new Map(map);
|
|
315
|
+
next.set(id, validated);
|
|
316
|
+
return next;
|
|
317
|
+
});
|
|
318
|
+
// Update indexes if provided
|
|
319
|
+
if (indexes && indexes.size > 0) {
|
|
320
|
+
yield* updateInIndex(indexes, previous, validated);
|
|
321
|
+
}
|
|
322
|
+
// Update search index if configured
|
|
323
|
+
if (searchIndexRef && searchIndexFields && searchIndexFields.length > 0) {
|
|
324
|
+
yield* updateInSearchIndex(searchIndexRef, previous, validated, searchIndexFields);
|
|
325
|
+
}
|
|
326
|
+
// Run afterUpdate hooks (fire-and-forget, errors swallowed)
|
|
327
|
+
yield* runAfterUpdateHooks(hooks?.afterUpdate, {
|
|
328
|
+
operation: "update",
|
|
329
|
+
collection: collectionName,
|
|
330
|
+
id,
|
|
331
|
+
previous,
|
|
332
|
+
current: validated,
|
|
333
|
+
update: transformedUpdates,
|
|
334
|
+
});
|
|
335
|
+
// Run onChange hooks with type: "update" (fire-and-forget, errors swallowed)
|
|
336
|
+
yield* runOnChangeHooks(hooks?.onChange, {
|
|
337
|
+
type: "update",
|
|
338
|
+
collection: collectionName,
|
|
339
|
+
id,
|
|
340
|
+
previous,
|
|
341
|
+
current: validated,
|
|
342
|
+
});
|
|
343
|
+
// Publish change event to reactive subscribers
|
|
344
|
+
if (changePubSub) {
|
|
345
|
+
yield* PubSub.publish(changePubSub, {
|
|
346
|
+
collection: collectionName,
|
|
347
|
+
operation: "update",
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
return validated;
|
|
351
|
+
});
|
|
352
|
+
// ============================================================================
|
|
353
|
+
// Update Multiple Entities
|
|
354
|
+
// ============================================================================
|
|
355
|
+
/**
|
|
356
|
+
* Update multiple entities matching a filter predicate.
|
|
357
|
+
*
|
|
358
|
+
* Uses a predicate function to select which entities to update.
|
|
359
|
+
* The caller (database factory) can use the Stream-based filter pipeline
|
|
360
|
+
* to build the predicate from a WhereClause.
|
|
361
|
+
*
|
|
362
|
+
* Runs hooks per entity: beforeUpdate can transform the update payload,
|
|
363
|
+
* afterUpdate and onChange run after state mutation.
|
|
364
|
+
*
|
|
365
|
+
* All matching entities are updated atomically in a single Ref.update call.
|
|
366
|
+
*/
|
|
367
|
+
export const updateMany = (collectionName, schema, relationships, ref, stateRefs, indexes, hooks, uniqueFields = [], computed, searchIndexRef, searchIndexFields, changePubSub) => (predicate, updates) => Effect.gen(function* () {
|
|
368
|
+
// Strip computed field keys from updates (they are derived, not stored)
|
|
369
|
+
const sanitizedUpdates = stripComputedFromUpdates(updates, computed);
|
|
370
|
+
// Validate immutable fields
|
|
371
|
+
const immutableCheck = validateImmutableFields(sanitizedUpdates);
|
|
372
|
+
if (!immutableCheck.valid) {
|
|
373
|
+
const fieldName = immutableCheck.field ?? "unknown";
|
|
374
|
+
return yield* Effect.fail(new ValidationError({
|
|
375
|
+
message: `Cannot update immutable field: ${fieldName}`,
|
|
376
|
+
issues: [
|
|
377
|
+
{
|
|
378
|
+
field: fieldName,
|
|
379
|
+
message: `Cannot update immutable field: ${fieldName}`,
|
|
380
|
+
},
|
|
381
|
+
],
|
|
382
|
+
}));
|
|
383
|
+
}
|
|
384
|
+
// Get current state and find matching entities
|
|
385
|
+
const currentMap = yield* Ref.get(ref);
|
|
386
|
+
const matchingEntities = [];
|
|
387
|
+
for (const entity of currentMap.values()) {
|
|
388
|
+
if (predicate(entity)) {
|
|
389
|
+
matchingEntities.push(entity);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (matchingEntities.length === 0) {
|
|
393
|
+
return { count: 0, updated: [] };
|
|
394
|
+
}
|
|
395
|
+
// Apply updates, run beforeUpdate hooks, and validate each entity
|
|
396
|
+
// We need to track both previous and validated for hooks later
|
|
397
|
+
const entityPairs = [];
|
|
398
|
+
for (const entity of matchingEntities) {
|
|
399
|
+
// Run beforeUpdate hooks (can transform the update payload)
|
|
400
|
+
const transformedUpdates = yield* runBeforeUpdateHooks(hooks?.beforeUpdate, {
|
|
401
|
+
operation: "update",
|
|
402
|
+
collection: collectionName,
|
|
403
|
+
id: entity.id,
|
|
404
|
+
existing: entity,
|
|
405
|
+
update: sanitizedUpdates,
|
|
406
|
+
});
|
|
407
|
+
const updated = applyUpdates(entity, transformedUpdates);
|
|
408
|
+
const validated = yield* validateEntity(schema, updated);
|
|
409
|
+
entityPairs.push({
|
|
410
|
+
previous: entity,
|
|
411
|
+
validated,
|
|
412
|
+
transformedUpdates: transformedUpdates,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
// Validate foreign keys if relationship fields were updated
|
|
416
|
+
const relationshipFields = Object.keys(relationships).map((field) => relationships[field].foreignKey || `${field}Id`);
|
|
417
|
+
const hasRelationshipUpdate = Object.keys(sanitizedUpdates).some((key) => relationshipFields.includes(key));
|
|
418
|
+
if (hasRelationshipUpdate) {
|
|
419
|
+
for (const { validated } of entityPairs) {
|
|
420
|
+
yield* validateForeignKeysEffect(validated, collectionName, relationships, stateRefs);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
// Check unique constraints if the update touches any unique fields
|
|
424
|
+
if (updateTouchesUniqueFields(sanitizedUpdates, uniqueFields)) {
|
|
425
|
+
// For updateMany, we need to check each entity against:
|
|
426
|
+
// 1. Existing entities (excluding entities being updated)
|
|
427
|
+
// 2. Other entities in the batch (they might conflict with each other)
|
|
428
|
+
// Create a temporary map that includes our updates for checking
|
|
429
|
+
const checkMap = new Map(currentMap);
|
|
430
|
+
for (const { validated } of entityPairs) {
|
|
431
|
+
checkMap.set(validated.id, validated);
|
|
432
|
+
}
|
|
433
|
+
for (const { validated } of entityPairs) {
|
|
434
|
+
// Check against all other entities (excluding self)
|
|
435
|
+
yield* checkUniqueConstraints(validated, checkMap, uniqueFields, collectionName);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
// Atomically update all matching entities in state
|
|
439
|
+
yield* Ref.update(ref, (map) => {
|
|
440
|
+
const next = new Map(map);
|
|
441
|
+
for (const { validated } of entityPairs) {
|
|
442
|
+
next.set(validated.id, validated);
|
|
443
|
+
}
|
|
444
|
+
return next;
|
|
445
|
+
});
|
|
446
|
+
// Update indexes if provided
|
|
447
|
+
if (indexes && indexes.size > 0) {
|
|
448
|
+
for (const { previous, validated } of entityPairs) {
|
|
449
|
+
yield* updateInIndex(indexes, previous, validated);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
// Update search index if configured
|
|
453
|
+
if (searchIndexRef && searchIndexFields && searchIndexFields.length > 0) {
|
|
454
|
+
for (const { previous, validated } of entityPairs) {
|
|
455
|
+
yield* updateInSearchIndex(searchIndexRef, previous, validated, searchIndexFields);
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
// Run afterUpdate and onChange hooks for each updated entity
|
|
459
|
+
for (const { previous, validated, transformedUpdates } of entityPairs) {
|
|
460
|
+
// Run afterUpdate hooks (fire-and-forget, errors swallowed)
|
|
461
|
+
yield* runAfterUpdateHooks(hooks?.afterUpdate, {
|
|
462
|
+
operation: "update",
|
|
463
|
+
collection: collectionName,
|
|
464
|
+
id: validated.id,
|
|
465
|
+
previous,
|
|
466
|
+
current: validated,
|
|
467
|
+
update: transformedUpdates,
|
|
468
|
+
});
|
|
469
|
+
// Run onChange hooks with type: "update" (fire-and-forget, errors swallowed)
|
|
470
|
+
yield* runOnChangeHooks(hooks?.onChange, {
|
|
471
|
+
type: "update",
|
|
472
|
+
collection: collectionName,
|
|
473
|
+
id: validated.id,
|
|
474
|
+
previous,
|
|
475
|
+
current: validated,
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
// Publish a single change event after all updates are complete
|
|
479
|
+
if (changePubSub && entityPairs.length > 0) {
|
|
480
|
+
yield* PubSub.publish(changePubSub, {
|
|
481
|
+
collection: collectionName,
|
|
482
|
+
operation: "update",
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
return {
|
|
486
|
+
count: entityPairs.length,
|
|
487
|
+
updated: entityPairs.map((p) => p.validated),
|
|
488
|
+
};
|
|
489
|
+
});
|
|
490
|
+
// ============================================================================
|
|
491
|
+
// Helper Functions
|
|
492
|
+
// ============================================================================
|
|
493
|
+
/**
|
|
494
|
+
* Extract fields that were actually changed between two entity versions.
|
|
495
|
+
*/
|
|
496
|
+
export function getChangedFields(original, updated) {
|
|
497
|
+
const changed = [];
|
|
498
|
+
for (const key of Object.keys(updated)) {
|
|
499
|
+
if (original[key] !== updated[key]) {
|
|
500
|
+
changed.push(String(key));
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return changed;
|
|
504
|
+
}
|
|
505
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/operations/crud/update.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effect-based upsert operations for entities.
|
|
3
|
+
*
|
|
4
|
+
* Uses Ref<ReadonlyMap> for atomic state mutation, Effect Schema for validation,
|
|
5
|
+
* and typed errors (ValidationError, ForeignKeyError).
|
|
6
|
+
*
|
|
7
|
+
* Upsert = find by `where` clause → update if exists, create if not.
|
|
8
|
+
*/
|
|
9
|
+
import { Effect, PubSub, Ref, type Schema } from "effect";
|
|
10
|
+
import type { ForeignKeyError, HookError, UniqueConstraintError, ValidationError } from "../../errors/crud-errors.js";
|
|
11
|
+
import type { UpsertInternalInput, UpsertManyResult, UpsertResult } from "../../types/crud-types.js";
|
|
12
|
+
import type { HooksConfig } from "../../types/hook-types.js";
|
|
13
|
+
import type { CollectionIndexes } from "../../types/index-types.js";
|
|
14
|
+
import type { ChangeEvent } from "../../types/reactive-types.js";
|
|
15
|
+
import type { SearchIndexMap } from "../../types/search-types.js";
|
|
16
|
+
import { type NormalizedConstraints } from "./unique-check.js";
|
|
17
|
+
type HasId = {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
};
|
|
20
|
+
type RelationshipConfig = {
|
|
21
|
+
readonly type: "ref" | "inverse";
|
|
22
|
+
readonly target: string;
|
|
23
|
+
readonly foreignKey?: string;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* Upsert a single entity: find by `where`, update if exists, create if not.
|
|
27
|
+
*
|
|
28
|
+
* Steps:
|
|
29
|
+
* 1. Look up entity by where clause in Ref state
|
|
30
|
+
* 2a. If found: run beforeUpdate hooks, apply update operators, validate, update in state, run afterUpdate/onChange
|
|
31
|
+
* 2b. If not found: merge where + create data, generate ID/timestamps, validate, run beforeCreate hooks, add to state, run afterCreate/onChange
|
|
32
|
+
* 3. Validate foreign key constraints
|
|
33
|
+
* 4. Return entity with __action metadata
|
|
34
|
+
*/
|
|
35
|
+
export declare const upsert: <T extends HasId, I = T>(collectionName: string, schema: Schema.Schema<T, I>, relationships: Record<string, RelationshipConfig>, ref: Ref.Ref<ReadonlyMap<string, T>>, stateRefs: Record<string, Ref.Ref<ReadonlyMap<string, HasId>>>, indexes?: CollectionIndexes, hooks?: HooksConfig<T>, uniqueFields?: NormalizedConstraints, searchIndexRef?: Ref.Ref<SearchIndexMap>, searchIndexFields?: ReadonlyArray<string>, changePubSub?: PubSub.PubSub<ChangeEvent>) => (input: UpsertInternalInput<T>) => Effect.Effect<UpsertResult<T>, ValidationError | ForeignKeyError | HookError | UniqueConstraintError>;
|
|
36
|
+
/**
|
|
37
|
+
* Upsert multiple entities efficiently.
|
|
38
|
+
*
|
|
39
|
+
* For each input:
|
|
40
|
+
* - If entity matches where clause: apply updates (or skip if unchanged)
|
|
41
|
+
* - If no match: create new entity
|
|
42
|
+
*
|
|
43
|
+
* All changes validated and applied atomically.
|
|
44
|
+
* Returns categorized results: created, updated, unchanged.
|
|
45
|
+
*
|
|
46
|
+
* Runs hooks per entity:
|
|
47
|
+
* - Create path: beforeCreate → mutation → afterCreate → onChange("create")
|
|
48
|
+
* - Update path: beforeUpdate → mutation → afterUpdate → onChange("update")
|
|
49
|
+
*/
|
|
50
|
+
export declare const upsertMany: <T extends HasId, I = T>(collectionName: string, schema: Schema.Schema<T, I>, relationships: Record<string, RelationshipConfig>, ref: Ref.Ref<ReadonlyMap<string, T>>, stateRefs: Record<string, Ref.Ref<ReadonlyMap<string, HasId>>>, indexes?: CollectionIndexes, hooks?: HooksConfig<T>, uniqueFields?: NormalizedConstraints, searchIndexRef?: Ref.Ref<SearchIndexMap>, searchIndexFields?: ReadonlyArray<string>, changePubSub?: PubSub.PubSub<ChangeEvent>) => (inputs: ReadonlyArray<UpsertInternalInput<T>>) => Effect.Effect<UpsertManyResult<T>, ValidationError | ForeignKeyError | HookError | UniqueConstraintError>;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=upsert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../../../src/operations/crud/upsert.ts"],"names":[],"mappings":"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"}
|