@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,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transaction support for atomic multi-collection operations.
|
|
3
|
+
*
|
|
4
|
+
* `createTransaction` returns a TransactionContext with collection accessors,
|
|
5
|
+
* commit/rollback methods, and mutation tracking. Mutations are visible
|
|
6
|
+
* immediately within the transaction (read-own-writes) and either committed
|
|
7
|
+
* atomically or rolled back to pre-transaction state.
|
|
8
|
+
*
|
|
9
|
+
* `$transaction` is a callback wrapper that auto-commits on success and
|
|
10
|
+
* auto-rolls back on failure.
|
|
11
|
+
*/
|
|
12
|
+
import { Effect, PubSub, Ref } from "effect";
|
|
13
|
+
import { TransactionError } from "../errors/crud-errors.js";
|
|
14
|
+
// ============================================================================
|
|
15
|
+
// createTransaction Factory
|
|
16
|
+
// ============================================================================
|
|
17
|
+
/**
|
|
18
|
+
* Create a new transaction context.
|
|
19
|
+
*
|
|
20
|
+
* Parameters:
|
|
21
|
+
* - stateRefs: The database's collection Refs (will be snapshotted and potentially restored)
|
|
22
|
+
* - transactionLock: Single-writer lock Ref (prevents concurrent transactions)
|
|
23
|
+
* - buildCollectionForTx: Callback to create collection accessors with transaction-aware mutations
|
|
24
|
+
* - persistenceTrigger: Optional trigger for scheduling saves on commit
|
|
25
|
+
* - changePubSub: Optional PubSub for reactive change notifications. When provided,
|
|
26
|
+
* individual mutation events are suppressed during the transaction and a single
|
|
27
|
+
* batch event is published for each mutated collection on commit.
|
|
28
|
+
*
|
|
29
|
+
* Returns an Effect that yields a TransactionContext. The context provides:
|
|
30
|
+
* - Collection accessors with the same interface as db.collectionName
|
|
31
|
+
* - commit() to finalize changes and trigger persistence
|
|
32
|
+
* - rollback() to restore snapshots and discard changes
|
|
33
|
+
* - isActive to check if transaction is still open
|
|
34
|
+
* - mutatedCollections to see which collections were written to
|
|
35
|
+
*
|
|
36
|
+
* On failure (e.g., lock already held), returns TransactionError.
|
|
37
|
+
*/
|
|
38
|
+
export const createTransaction = (stateRefs, transactionLock, buildCollectionForTx, persistenceTrigger, changePubSub) => Effect.gen(function* () {
|
|
39
|
+
// Task 2.3: Single-writer lock - atomically check and acquire via Ref.modify
|
|
40
|
+
const lockAcquired = yield* Ref.modify(transactionLock, (locked) => {
|
|
41
|
+
if (locked) {
|
|
42
|
+
return [false, true]; // Lock not acquired, stays locked
|
|
43
|
+
}
|
|
44
|
+
return [true, true]; // Lock acquired, now locked
|
|
45
|
+
});
|
|
46
|
+
if (!lockAcquired) {
|
|
47
|
+
return yield* new TransactionError({
|
|
48
|
+
operation: "begin",
|
|
49
|
+
reason: "another transaction is already active",
|
|
50
|
+
message: "Cannot begin transaction: another transaction is already active",
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// Task 2.2: Capture snapshots on begin
|
|
54
|
+
// Snapshot all collections upfront (O(n) Ref.get, each is O(1) - copies the reference)
|
|
55
|
+
const snapshots = new Map();
|
|
56
|
+
for (const [name, ref] of Object.entries(stateRefs)) {
|
|
57
|
+
const snapshot = yield* Ref.get(ref);
|
|
58
|
+
snapshots.set(name, snapshot);
|
|
59
|
+
}
|
|
60
|
+
// Task 2.7: Mutation tracking set
|
|
61
|
+
// CRUD operations call addMutation(collectionName) instead of scheduling persistence writes.
|
|
62
|
+
// On commit, persistenceTrigger.schedule is called for each collection in this set.
|
|
63
|
+
// On rollback, this set is simply discarded (no persistence writes).
|
|
64
|
+
const mutatedCollections = new Set();
|
|
65
|
+
// isActive flag - guards all transaction operations
|
|
66
|
+
let isActive = true;
|
|
67
|
+
// Build the addMutation callback
|
|
68
|
+
const addMutation = (collectionName) => {
|
|
69
|
+
mutatedCollections.add(collectionName);
|
|
70
|
+
};
|
|
71
|
+
// Helper to check if transaction is still active before any operation
|
|
72
|
+
const checkActive = () => Effect.suspend(() => isActive
|
|
73
|
+
? Effect.void
|
|
74
|
+
: new TransactionError({
|
|
75
|
+
operation: "begin",
|
|
76
|
+
reason: "transaction is no longer active",
|
|
77
|
+
message: "Cannot perform operation: transaction is no longer active",
|
|
78
|
+
}));
|
|
79
|
+
// Helper to wrap an effect-returning method with isActive check
|
|
80
|
+
const wrapWithActiveCheck = (effect) => Effect.flatMap(checkActive(), () => effect);
|
|
81
|
+
// Build collection accessors with isActive guards
|
|
82
|
+
const collections = {};
|
|
83
|
+
for (const collectionName of Object.keys(stateRefs)) {
|
|
84
|
+
const baseCollection = buildCollectionForTx(collectionName, addMutation);
|
|
85
|
+
// Wrap each method to check isActive before proceeding
|
|
86
|
+
// Note: query returns Stream/CursorPage which need different handling
|
|
87
|
+
collections[collectionName] = {
|
|
88
|
+
...baseCollection,
|
|
89
|
+
create: (...args) => wrapWithActiveCheck(baseCollection.create(...args)),
|
|
90
|
+
createMany: (...args) => wrapWithActiveCheck(baseCollection.createMany(...args)),
|
|
91
|
+
update: (...args) => wrapWithActiveCheck(baseCollection.update(...args)),
|
|
92
|
+
updateMany: (...args) => wrapWithActiveCheck(baseCollection.updateMany(...args)),
|
|
93
|
+
delete: (...args) => wrapWithActiveCheck(baseCollection.delete(...args)),
|
|
94
|
+
deleteMany: (...args) => wrapWithActiveCheck(baseCollection.deleteMany(...args)),
|
|
95
|
+
upsert: (...args) => wrapWithActiveCheck(baseCollection.upsert(...args)),
|
|
96
|
+
upsertMany: (...args) => wrapWithActiveCheck(baseCollection.upsertMany(...args)),
|
|
97
|
+
findById: (...args) => wrapWithActiveCheck(baseCollection.findById(...args)),
|
|
98
|
+
createWithRelationships: (...args) => wrapWithActiveCheck(baseCollection.createWithRelationships(...args)),
|
|
99
|
+
updateWithRelationships: (...args) => wrapWithActiveCheck(baseCollection.updateWithRelationships(...args)),
|
|
100
|
+
deleteWithRelationships: (...args) => wrapWithActiveCheck(baseCollection.deleteWithRelationships(...args)),
|
|
101
|
+
deleteManyWithRelationships: (...args) => wrapWithActiveCheck(baseCollection.deleteManyWithRelationships(...args)),
|
|
102
|
+
// aggregate uses the base implementation since reads don't modify state
|
|
103
|
+
// and its conditional return type is incompatible with wrapWithActiveCheck
|
|
104
|
+
aggregate: baseCollection.aggregate,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
const commit = () => Effect.gen(function* () {
|
|
108
|
+
if (!isActive) {
|
|
109
|
+
return yield* new TransactionError({
|
|
110
|
+
operation: "commit",
|
|
111
|
+
reason: "transaction is no longer active",
|
|
112
|
+
message: "Cannot commit: transaction is no longer active",
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
// Trigger persistence for mutated collections
|
|
116
|
+
if (persistenceTrigger) {
|
|
117
|
+
for (const name of mutatedCollections) {
|
|
118
|
+
persistenceTrigger.schedule(name);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Publish change events for each mutated collection (one event per collection)
|
|
122
|
+
// This notifies reactive subscribers about the committed changes
|
|
123
|
+
if (changePubSub) {
|
|
124
|
+
for (const collectionName of mutatedCollections) {
|
|
125
|
+
yield* PubSub.publish(changePubSub, {
|
|
126
|
+
collection: collectionName,
|
|
127
|
+
operation: "update",
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Release lock
|
|
132
|
+
yield* Ref.set(transactionLock, false);
|
|
133
|
+
isActive = false;
|
|
134
|
+
});
|
|
135
|
+
const rollback = () => Effect.gen(function* () {
|
|
136
|
+
if (!isActive) {
|
|
137
|
+
return yield* new TransactionError({
|
|
138
|
+
operation: "rollback",
|
|
139
|
+
reason: "transaction is no longer active",
|
|
140
|
+
message: "Cannot rollback: transaction is no longer active",
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
// Restore snapshots
|
|
144
|
+
for (const [name, snapshot] of snapshots) {
|
|
145
|
+
const ref = stateRefs[name];
|
|
146
|
+
if (ref) {
|
|
147
|
+
yield* Ref.set(ref, snapshot);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
// Release lock
|
|
151
|
+
yield* Ref.set(transactionLock, false);
|
|
152
|
+
isActive = false;
|
|
153
|
+
// NOTE: We deliberately do NOT publish any ChangeEvents on rollback.
|
|
154
|
+
// Reactive subscribers should never see tentative transaction state.
|
|
155
|
+
// Only committed changes trigger notifications (see commit()).
|
|
156
|
+
// Rollback always fails to short-circuit
|
|
157
|
+
return yield* new TransactionError({
|
|
158
|
+
operation: "rollback",
|
|
159
|
+
reason: "transaction rolled back",
|
|
160
|
+
message: "Transaction rolled back",
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
// Build the TransactionContext
|
|
164
|
+
const ctx = {
|
|
165
|
+
commit,
|
|
166
|
+
rollback,
|
|
167
|
+
get isActive() {
|
|
168
|
+
return isActive;
|
|
169
|
+
},
|
|
170
|
+
get mutatedCollections() {
|
|
171
|
+
return mutatedCollections;
|
|
172
|
+
},
|
|
173
|
+
...collections,
|
|
174
|
+
};
|
|
175
|
+
return ctx;
|
|
176
|
+
});
|
|
177
|
+
// ============================================================================
|
|
178
|
+
// $transaction Callback Wrapper
|
|
179
|
+
// ============================================================================
|
|
180
|
+
/**
|
|
181
|
+
* Execute a callback within an atomic transaction context.
|
|
182
|
+
*
|
|
183
|
+
* All CRUD operations inside the callback operate against the live in-memory state.
|
|
184
|
+
* On success, changes are committed and persistence is triggered.
|
|
185
|
+
* On failure (error thrown or explicit rollback), all mutations are reverted.
|
|
186
|
+
*
|
|
187
|
+
* Usage:
|
|
188
|
+
* ```ts
|
|
189
|
+
* const result = await db.$transaction((ctx) =>
|
|
190
|
+
* Effect.gen(function* () {
|
|
191
|
+
* const user = yield* ctx.users.create({ name: "Alice" })
|
|
192
|
+
* const post = yield* ctx.posts.create({ authorId: user.id, title: "Hello" })
|
|
193
|
+
* return { user, post }
|
|
194
|
+
* })
|
|
195
|
+
* ).pipe(Effect.runPromise)
|
|
196
|
+
* ```
|
|
197
|
+
*
|
|
198
|
+
* @param stateRefs - The database's collection Refs
|
|
199
|
+
* @param transactionLock - Single-writer lock Ref
|
|
200
|
+
* @param buildCollectionForTx - Callback to create collection accessors
|
|
201
|
+
* @param persistenceTrigger - Optional trigger for scheduling saves on commit
|
|
202
|
+
* @param changePubSub - Optional PubSub for reactive change notifications
|
|
203
|
+
* @param fn - The callback to execute within the transaction
|
|
204
|
+
* @returns Effect that yields the callback result, with TransactionError in error channel
|
|
205
|
+
*/
|
|
206
|
+
export const $transaction = (stateRefs, transactionLock, buildCollectionForTx, persistenceTrigger, changePubSub, fn) => Effect.gen(function* () {
|
|
207
|
+
// Task 3.2: Check for nested transactions before attempting to acquire lock
|
|
208
|
+
// $transaction is the user-facing callback API, so if the lock is already held
|
|
209
|
+
// when $transaction is called, it's a nested transaction attempt.
|
|
210
|
+
const isLocked = yield* Ref.get(transactionLock);
|
|
211
|
+
if (isLocked) {
|
|
212
|
+
return yield* new TransactionError({
|
|
213
|
+
operation: "begin",
|
|
214
|
+
reason: "nested transactions not supported",
|
|
215
|
+
message: "Cannot begin transaction: nested transactions not supported",
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
// Create the transaction context
|
|
219
|
+
const ctx = yield* createTransaction(stateRefs, transactionLock, buildCollectionForTx, persistenceTrigger, changePubSub);
|
|
220
|
+
// Run the callback and handle success/failure
|
|
221
|
+
const result = yield* fn(ctx).pipe(
|
|
222
|
+
// On success: commit and return the result
|
|
223
|
+
Effect.flatMap((value) => Effect.gen(function* () {
|
|
224
|
+
yield* ctx.commit();
|
|
225
|
+
return value;
|
|
226
|
+
})),
|
|
227
|
+
// On failure: rollback and re-raise the original error
|
|
228
|
+
Effect.catchAll((error) => Effect.gen(function* () {
|
|
229
|
+
// Only rollback if still active (might have been explicitly rolled back)
|
|
230
|
+
if (ctx.isActive) {
|
|
231
|
+
// Rollback always fails with TransactionError, but we want to
|
|
232
|
+
// re-raise the original error, so we catch the rollback error
|
|
233
|
+
yield* ctx.rollback().pipe(Effect.catchAll(() => Effect.void));
|
|
234
|
+
}
|
|
235
|
+
// Re-raise the original error
|
|
236
|
+
return yield* Effect.fail(error);
|
|
237
|
+
})));
|
|
238
|
+
return result;
|
|
239
|
+
});
|
|
240
|
+
//# sourceMappingURL=transaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.js","sourceRoot":"","sources":["../../src/transactions/transaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aggregate types for scalar and grouped aggregations.
|
|
3
|
+
*
|
|
4
|
+
* Scalar aggregates compute a single result from a filtered set.
|
|
5
|
+
* Grouped aggregates partition by field values and compute aggregates per group.
|
|
6
|
+
*/
|
|
7
|
+
import type { WhereClause } from "./types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Result of a scalar aggregate operation.
|
|
10
|
+
* Only requested aggregations appear in the result.
|
|
11
|
+
*/
|
|
12
|
+
export interface AggregateResult {
|
|
13
|
+
readonly count?: number;
|
|
14
|
+
readonly sum?: Record<string, number>;
|
|
15
|
+
readonly avg?: Record<string, number | null>;
|
|
16
|
+
readonly min?: Record<string, unknown>;
|
|
17
|
+
readonly max?: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* A single group's result in a grouped aggregation.
|
|
21
|
+
* Contains the grouping field values and the computed aggregates.
|
|
22
|
+
*/
|
|
23
|
+
export interface GroupResult extends AggregateResult {
|
|
24
|
+
readonly group: Record<string, unknown>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Result of a grouped aggregate operation.
|
|
28
|
+
* Array of group objects ordered by first-encounter.
|
|
29
|
+
*/
|
|
30
|
+
export type GroupedAggregateResult = ReadonlyArray<GroupResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Base aggregate options shared by both scalar and grouped configs.
|
|
33
|
+
*/
|
|
34
|
+
interface AggregateOptions {
|
|
35
|
+
readonly count?: true;
|
|
36
|
+
readonly sum?: string | ReadonlyArray<string>;
|
|
37
|
+
readonly avg?: string | ReadonlyArray<string>;
|
|
38
|
+
readonly min?: string | ReadonlyArray<string>;
|
|
39
|
+
readonly max?: string | ReadonlyArray<string>;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Configuration for scalar aggregation (no grouping).
|
|
43
|
+
* Generic over entity type, relations, and database for where clause typing.
|
|
44
|
+
*/
|
|
45
|
+
export interface ScalarAggregateConfig<T = unknown, Relations = unknown, DB = unknown> extends AggregateOptions {
|
|
46
|
+
readonly where?: WhereClause<T, Relations, DB>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Configuration for grouped aggregation.
|
|
50
|
+
* Extends scalar config with required groupBy field.
|
|
51
|
+
*/
|
|
52
|
+
export interface GroupedAggregateConfig<T = unknown, Relations = unknown, DB = unknown> extends ScalarAggregateConfig<T, Relations, DB> {
|
|
53
|
+
readonly groupBy: string | ReadonlyArray<string>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Union type for aggregate configuration.
|
|
57
|
+
* The presence of `groupBy` distinguishes grouped from scalar aggregation.
|
|
58
|
+
*/
|
|
59
|
+
export type AggregateConfig<T = unknown, Relations = unknown, DB = unknown> = ScalarAggregateConfig<T, Relations, DB> | GroupedAggregateConfig<T, Relations, DB>;
|
|
60
|
+
/**
|
|
61
|
+
* Check if a config is for grouped aggregation.
|
|
62
|
+
*/
|
|
63
|
+
export declare const isGroupedAggregateConfig: <T, Relations, DB>(config: AggregateConfig<T, Relations, DB>) => config is GroupedAggregateConfig<T, Relations, DB>;
|
|
64
|
+
/**
|
|
65
|
+
* Infer the return type based on config.
|
|
66
|
+
* - With groupBy → GroupedAggregateResult (array of group objects)
|
|
67
|
+
* - Without groupBy → AggregateResult (single object)
|
|
68
|
+
*/
|
|
69
|
+
export type InferAggregateResult<Config extends AggregateConfig> = Config extends {
|
|
70
|
+
readonly groupBy: string | ReadonlyArray<string>;
|
|
71
|
+
} ? GroupedAggregateResult : AggregateResult;
|
|
72
|
+
export {};
|
|
73
|
+
//# sourceMappingURL=aggregate-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate-types.d.ts","sourceRoot":"","sources":["../../src/types/aggregate-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAM9C;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IAC7C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED;;;GAGG;AACH,MAAM,WAAW,WAAY,SAAQ,eAAe;IACnD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AAED;;;GAGG;AACH,MAAM,MAAM,sBAAsB,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;AAMhE;;GAEG;AACH,UAAU,gBAAgB;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC;IACtB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAC9C,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;CAC9C;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB,CACrC,CAAC,GAAG,OAAO,EACX,SAAS,GAAG,OAAO,EACnB,EAAE,GAAG,OAAO,CACX,SAAQ,gBAAgB;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;CAC/C;AAED;;;GAGG;AACH,MAAM,WAAW,sBAAsB,CACtC,CAAC,GAAG,OAAO,EACX,SAAS,GAAG,OAAO,EACnB,EAAE,GAAG,OAAO,CACX,SAAQ,qBAAqB,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC;IAChD,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;CACjD;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,GAAG,OAAO,EAAE,SAAS,GAAG,OAAO,EAAE,EAAE,GAAG,OAAO,IACvE,qBAAqB,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,GACvC,sBAAsB,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,CAAC;AAM5C;;GAEG;AACH,eAAO,MAAM,wBAAwB,GAAI,CAAC,EAAE,SAAS,EAAE,EAAE,EACxD,QAAQ,eAAe,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CAAC,KACvC,MAAM,IAAI,sBAAsB,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,CACA,CAAC;AAMrD;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,CAAC,MAAM,SAAS,eAAe,IAC9D,MAAM,SAAS;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;CAAE,GAChE,sBAAsB,GACtB,eAAe,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aggregate types for scalar and grouped aggregations.
|
|
3
|
+
*
|
|
4
|
+
* Scalar aggregates compute a single result from a filtered set.
|
|
5
|
+
* Grouped aggregates partition by field values and compute aggregates per group.
|
|
6
|
+
*/
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Type Guards
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Check if a config is for grouped aggregation.
|
|
12
|
+
*/
|
|
13
|
+
export const isGroupedAggregateConfig = (config) => "groupBy" in config && config.groupBy !== undefined;
|
|
14
|
+
//# sourceMappingURL=aggregate-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate-types.js","sourceRoot":"","sources":["../../src/types/aggregate-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAiFH,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E;;GAEG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACvC,MAAyC,EACY,EAAE,CACvD,SAAS,IAAI,MAAM,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for computed fields.
|
|
3
|
+
*
|
|
4
|
+
* Computed fields are derived at query time from stored entity data.
|
|
5
|
+
* They are never persisted to disk - only materialized in the query pipeline.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* A computed field derivation function.
|
|
9
|
+
* Takes the full entity (with populated relationships if applicable) and returns the computed value.
|
|
10
|
+
*
|
|
11
|
+
* @template T - The entity type (may include populated relationship data)
|
|
12
|
+
* @template R - The return type of the computed field
|
|
13
|
+
*/
|
|
14
|
+
export type ComputedFieldDefinition<T, R> = (entity: T) => R;
|
|
15
|
+
/**
|
|
16
|
+
* Configuration object mapping computed field names to their derivation functions.
|
|
17
|
+
*
|
|
18
|
+
* @template T - The entity type that computed fields derive from
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const computed = {
|
|
23
|
+
* displayName: (book) => `${book.title} (${book.year})`,
|
|
24
|
+
* isClassic: (book) => book.year < 1980,
|
|
25
|
+
* } satisfies ComputedFieldsConfig<Book>
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export type ComputedFieldsConfig<T> = Record<string, ComputedFieldDefinition<T, unknown>>;
|
|
29
|
+
/**
|
|
30
|
+
* Infer the shape of computed fields from a config object.
|
|
31
|
+
* Maps each key in the config to the return type of its derivation function.
|
|
32
|
+
*
|
|
33
|
+
* @template C - The computed fields config object type
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* type Config = {
|
|
38
|
+
* displayName: (b: Book) => string;
|
|
39
|
+
* isClassic: (b: Book) => boolean;
|
|
40
|
+
* }
|
|
41
|
+
* type Computed = InferComputedFields<Config>
|
|
42
|
+
* // { displayName: string; isClassic: boolean }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export type InferComputedFields<C> = C extends ComputedFieldsConfig<infer _> ? {
|
|
46
|
+
readonly [K in keyof C]: C[K] extends ComputedFieldDefinition<infer _T, infer R> ? R : never;
|
|
47
|
+
} : Record<string, never>;
|
|
48
|
+
/**
|
|
49
|
+
* Merge stored entity type with inferred computed fields.
|
|
50
|
+
* The result is the full entity shape as seen in query results.
|
|
51
|
+
*
|
|
52
|
+
* @template T - The stored entity type
|
|
53
|
+
* @template C - The computed fields config
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```ts
|
|
57
|
+
* type Book = { id: string; title: string; year: number }
|
|
58
|
+
* type Config = { displayName: (b: Book) => string }
|
|
59
|
+
* type Full = WithComputed<Book, Config>
|
|
60
|
+
* // { id: string; title: string; year: number; readonly displayName: string }
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export type WithComputed<T, C> = T & InferComputedFields<C>;
|
|
64
|
+
/**
|
|
65
|
+
* Extract computed field keys from a config object.
|
|
66
|
+
* Useful for checking if a select clause includes computed fields.
|
|
67
|
+
*
|
|
68
|
+
* @template C - The computed fields config object type
|
|
69
|
+
*/
|
|
70
|
+
export type ComputedFieldKeys<C> = C extends ComputedFieldsConfig<infer _> ? keyof C : never;
|
|
71
|
+
//# sourceMappingURL=computed-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computed-types.d.ts","sourceRoot":"","sources":["../../src/types/computed-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;;GAMG;AACH,MAAM,MAAM,uBAAuB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;AAE7D;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,oBAAoB,CAAC,CAAC,IAAI,MAAM,CAC3C,MAAM,EACN,uBAAuB,CAAC,CAAC,EAAE,OAAO,CAAC,CACnC,CAAC;AAEF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,mBAAmB,CAAC,CAAC,IAChC,CAAC,SAAS,oBAAoB,CAAC,MAAM,CAAC,CAAC,GACpC;IACA,QAAQ,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,uBAAuB,CAC5D,MAAM,EAAE,EACR,MAAM,CAAC,CACP,GACE,CAAC,GACD,KAAK;CACR,GACA,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AAE1B;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,YAAY,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAC9B,CAAC,SAAS,oBAAoB,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,KAAK,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"computed-types.js","sourceRoot":"","sources":["../../src/types/computed-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for CRUD operations with relationships
|
|
3
|
+
* Implements Phase 2 relationship features with full type safety
|
|
4
|
+
*/
|
|
5
|
+
import type { CreateInput, UpdateInput } from "./crud-types.js";
|
|
6
|
+
import type { RelationshipDef } from "./types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Input type for connecting to existing entities
|
|
9
|
+
* Supports connection by ID or any unique field combination
|
|
10
|
+
*/
|
|
11
|
+
export type ConnectInput<T> = {
|
|
12
|
+
id: string;
|
|
13
|
+
} | Partial<T>;
|
|
14
|
+
/**
|
|
15
|
+
* Input type for connect or create pattern
|
|
16
|
+
* If entity doesn't exist, create it with provided data
|
|
17
|
+
*/
|
|
18
|
+
export type ConnectOrCreateInput<T> = {
|
|
19
|
+
where: ConnectInput<T>;
|
|
20
|
+
create: CreateInput<T>;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Input type for updating with where clause
|
|
24
|
+
* Used for updating specific items in many-to-many relationships
|
|
25
|
+
*/
|
|
26
|
+
export type UpdateWithWhereInput<T> = {
|
|
27
|
+
where: ConnectInput<T>;
|
|
28
|
+
data: UpdateInput<T>;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Operations available for single (ref) relationships
|
|
32
|
+
*/
|
|
33
|
+
export type SingleRelationshipInput<T> = {
|
|
34
|
+
$connect?: ConnectInput<T>;
|
|
35
|
+
$disconnect?: boolean;
|
|
36
|
+
$create?: CreateInput<T>;
|
|
37
|
+
$connectOrCreate?: ConnectOrCreateInput<T>;
|
|
38
|
+
$update?: UpdateInput<T>;
|
|
39
|
+
$delete?: boolean;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Operations available for many (inverse) relationships
|
|
43
|
+
*/
|
|
44
|
+
export type ManyRelationshipInput<T> = {
|
|
45
|
+
$connect?: ConnectInput<T> | ConnectInput<T>[];
|
|
46
|
+
$disconnect?: ConnectInput<T> | ConnectInput<T>[] | boolean;
|
|
47
|
+
$create?: CreateInput<T> | CreateInput<T>[];
|
|
48
|
+
$createMany?: CreateInput<T>[];
|
|
49
|
+
$update?: UpdateWithWhereInput<T> | UpdateWithWhereInput<T>[];
|
|
50
|
+
$updateMany?: {
|
|
51
|
+
where: Partial<T>;
|
|
52
|
+
data: UpdateInput<T>;
|
|
53
|
+
};
|
|
54
|
+
$delete?: ConnectInput<T> | ConnectInput<T>[];
|
|
55
|
+
$deleteMany?: Partial<T>;
|
|
56
|
+
$set?: ConnectInput<T>[];
|
|
57
|
+
$connectOrCreate?: ConnectOrCreateInput<T> | ConnectOrCreateInput<T>[];
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Extract relationship input type based on relationship type
|
|
61
|
+
*/
|
|
62
|
+
export type RelationshipInput<R> = R extends RelationshipDef<infer T, "ref"> ? SingleRelationshipInput<T> | ConnectInput<T> : R extends RelationshipDef<infer T, "inverse"> ? ManyRelationshipInput<T> : never;
|
|
63
|
+
/**
|
|
64
|
+
* Transform entity relationships for create input
|
|
65
|
+
* Allows relationship operations during entity creation
|
|
66
|
+
*/
|
|
67
|
+
export type CreateWithRelationshipsInput<T, Relations> = CreateInput<T> & {
|
|
68
|
+
[K in keyof Relations]?: RelationshipInput<Relations[K]>;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Transform entity relationships for update input
|
|
72
|
+
* Allows relationship operations during entity update
|
|
73
|
+
*/
|
|
74
|
+
export type UpdateWithRelationshipsInput<T, Relations> = UpdateInput<T> & {
|
|
75
|
+
[K in keyof Relations]?: RelationshipInput<Relations[K]>;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Cascade behavior options for delete operations
|
|
79
|
+
*/
|
|
80
|
+
export type CascadeOption = "cascade" | "restrict" | "set_null" | "cascade_soft" | "preserve";
|
|
81
|
+
/**
|
|
82
|
+
* Delete options with cascade configuration
|
|
83
|
+
*/
|
|
84
|
+
export type DeleteWithRelationshipsOptions<_T, Relations> = {
|
|
85
|
+
soft?: boolean;
|
|
86
|
+
returnDeleted?: boolean;
|
|
87
|
+
include?: {
|
|
88
|
+
[K in keyof Relations]?: CascadeOption;
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Result of delete operation with cascade information
|
|
93
|
+
*/
|
|
94
|
+
export type DeleteWithRelationshipsResult<T> = {
|
|
95
|
+
deleted: T;
|
|
96
|
+
cascaded?: {
|
|
97
|
+
[collection: string]: {
|
|
98
|
+
count: number;
|
|
99
|
+
ids: string[];
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Options for batch operations with relationships
|
|
105
|
+
*/
|
|
106
|
+
export type BatchRelationshipOptions = {
|
|
107
|
+
validateRelationships?: boolean;
|
|
108
|
+
skipDuplicates?: boolean;
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Result of batch operations with relationship information
|
|
112
|
+
*/
|
|
113
|
+
export type BatchRelationshipResult<T> = {
|
|
114
|
+
success: T[];
|
|
115
|
+
failed: Array<{
|
|
116
|
+
data: Partial<T>;
|
|
117
|
+
error: string;
|
|
118
|
+
index: number;
|
|
119
|
+
}>;
|
|
120
|
+
cascaded?: {
|
|
121
|
+
[collection: string]: {
|
|
122
|
+
count: number;
|
|
123
|
+
action: CascadeOption;
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Relationship constraint validation
|
|
129
|
+
*/
|
|
130
|
+
export type RelationshipConstraint = {
|
|
131
|
+
type: "max_count" | "unique" | "required";
|
|
132
|
+
field: string;
|
|
133
|
+
value?: unknown;
|
|
134
|
+
message: string;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Foreign key violation error details
|
|
138
|
+
*/
|
|
139
|
+
export type ForeignKeyViolation = {
|
|
140
|
+
field: string;
|
|
141
|
+
targetCollection: string;
|
|
142
|
+
missingId: string;
|
|
143
|
+
message: string;
|
|
144
|
+
};
|
|
145
|
+
/**
|
|
146
|
+
* Restrict violation error details
|
|
147
|
+
*/
|
|
148
|
+
export type RestrictViolation = {
|
|
149
|
+
collection: string;
|
|
150
|
+
relatedCollection: string;
|
|
151
|
+
relatedCount: number;
|
|
152
|
+
message: string;
|
|
153
|
+
};
|
|
154
|
+
/**
|
|
155
|
+
* Check if a relationship input contains operations
|
|
156
|
+
*/
|
|
157
|
+
export declare function isRelationshipOperation(value: unknown): value is Record<string, unknown>;
|
|
158
|
+
/**
|
|
159
|
+
* Extract entity type from relationship definition
|
|
160
|
+
*/
|
|
161
|
+
export type ExtractRelationshipEntity<R> = R extends RelationshipDef<infer T, infer _> ? T : never;
|
|
162
|
+
/**
|
|
163
|
+
* Extract relationship type (ref/inverse) from definition
|
|
164
|
+
*/
|
|
165
|
+
export type ExtractRelationshipType<R> = R extends RelationshipDef<infer _, infer Type> ? Type : never;
|
|
166
|
+
/**
|
|
167
|
+
* Filter relationships by type
|
|
168
|
+
*/
|
|
169
|
+
export type FilterRelationshipsByType<Relations, Type extends "ref" | "inverse"> = {
|
|
170
|
+
[K in keyof Relations as Relations[K] extends RelationshipDef<infer _, Type> ? K : never]: Relations[K];
|
|
171
|
+
};
|
|
172
|
+
/**
|
|
173
|
+
* Get ref relationships only
|
|
174
|
+
*/
|
|
175
|
+
export type RefRelationships<Relations> = FilterRelationshipsByType<Relations, "ref">;
|
|
176
|
+
/**
|
|
177
|
+
* Get inverse relationships only
|
|
178
|
+
*/
|
|
179
|
+
export type InverseRelationships<Relations> = FilterRelationshipsByType<Relations, "inverse">;
|
|
180
|
+
//# sourceMappingURL=crud-relationship-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud-relationship-types.d.ts","sourceRoot":"","sources":["../../src/types/crud-relationship-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for CRUD operations with relationships
|
|
3
|
+
* Implements Phase 2 relationship features with full type safety
|
|
4
|
+
*/
|
|
5
|
+
// ============================================================================
|
|
6
|
+
// Type Helpers
|
|
7
|
+
// ============================================================================
|
|
8
|
+
/**
|
|
9
|
+
* Check if a relationship input contains operations
|
|
10
|
+
*/
|
|
11
|
+
export function isRelationshipOperation(value) {
|
|
12
|
+
if (typeof value !== "object" || value === null)
|
|
13
|
+
return false;
|
|
14
|
+
const keys = Object.keys(value);
|
|
15
|
+
return keys.some((key) => key.startsWith("$"));
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=crud-relationship-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crud-relationship-types.js","sourceRoot":"","sources":["../../src/types/crud-relationship-types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA4MH,+EAA+E;AAC/E,eAAe;AACf,+EAA+E;AAE/E;;GAEG;AACH,MAAM,UAAU,uBAAuB,CACtC,KAAc;IAEd,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AAChD,CAAC"}
|