@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,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data transformation utilities for converting between internal formats
|
|
3
|
+
* (ReadonlyMap and array) and storage object format, plus collection
|
|
4
|
+
* file grouping utilities.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Convert an array of entities with id fields to an object keyed by id.
|
|
8
|
+
* This provides O(1) lookups in storage files.
|
|
9
|
+
*
|
|
10
|
+
* @param items - Array of entities, each must have an 'id' field
|
|
11
|
+
* @returns Object keyed by entity id
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* arrayToObject([
|
|
15
|
+
* { id: 'user-1', name: 'Alice' },
|
|
16
|
+
* { id: 'user-2', name: 'Bob' }
|
|
17
|
+
* ])
|
|
18
|
+
* // Returns: {
|
|
19
|
+
* // 'user-1': { id: 'user-1', name: 'Alice' },
|
|
20
|
+
* // 'user-2': { id: 'user-2', name: 'Bob' }
|
|
21
|
+
* // }
|
|
22
|
+
*/
|
|
23
|
+
export declare function arrayToObject<T extends {
|
|
24
|
+
id: string;
|
|
25
|
+
}>(items: readonly T[]): Record<string, T>;
|
|
26
|
+
/**
|
|
27
|
+
* Convert an object keyed by id back to an array of entities.
|
|
28
|
+
*
|
|
29
|
+
* @param obj - Object keyed by entity id
|
|
30
|
+
* @returns Array of entities
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* objectToArray({
|
|
34
|
+
* 'user-1': { id: 'user-1', name: 'Alice' },
|
|
35
|
+
* 'user-2': { id: 'user-2', name: 'Bob' }
|
|
36
|
+
* })
|
|
37
|
+
* // Returns: [
|
|
38
|
+
* // { id: 'user-1', name: 'Alice' },
|
|
39
|
+
* // { id: 'user-2', name: 'Bob' }
|
|
40
|
+
* // ]
|
|
41
|
+
*/
|
|
42
|
+
export declare function objectToArray<T>(obj: Record<string, T>): T[];
|
|
43
|
+
/**
|
|
44
|
+
* Collection configuration that may include a file path for persistence
|
|
45
|
+
*/
|
|
46
|
+
type CollectionConfig = {
|
|
47
|
+
readonly file?: string;
|
|
48
|
+
readonly [key: string]: unknown;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Group collections by their configured file paths.
|
|
52
|
+
* Collections without a file path are not included in the result.
|
|
53
|
+
*
|
|
54
|
+
* @param config - Database configuration with collection definitions
|
|
55
|
+
* @returns Map from file path to array of collection names that use that file
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* groupByFile({
|
|
59
|
+
* users: { schema: UserSchema, file: '/data/users.json' },
|
|
60
|
+
* products: { schema: ProductSchema, file: '/data/db.json' },
|
|
61
|
+
* categories: { schema: CategorySchema, file: '/data/db.json' },
|
|
62
|
+
* sessions: { schema: SessionSchema } // no file = in-memory only
|
|
63
|
+
* })
|
|
64
|
+
* // Returns: Map {
|
|
65
|
+
* // '/data/users.json' => ['users'],
|
|
66
|
+
* // '/data/db.json' => ['products', 'categories']
|
|
67
|
+
* // }
|
|
68
|
+
*/
|
|
69
|
+
export declare function groupByFile<Config extends Record<string, CollectionConfig>>(config: Config): Map<string, string[]>;
|
|
70
|
+
/**
|
|
71
|
+
* Get all unique file paths from a database configuration.
|
|
72
|
+
*
|
|
73
|
+
* @param config - Database configuration with collection definitions
|
|
74
|
+
* @returns Array of unique file paths used by collections
|
|
75
|
+
*/
|
|
76
|
+
export declare function getConfigFilePaths<Config extends Record<string, CollectionConfig>>(config: Config): string[];
|
|
77
|
+
/**
|
|
78
|
+
* Check if a collection is configured for persistence.
|
|
79
|
+
*
|
|
80
|
+
* @param config - Database configuration
|
|
81
|
+
* @param collectionName - Name of the collection to check
|
|
82
|
+
* @returns True if the collection has a file path configured
|
|
83
|
+
*/
|
|
84
|
+
export declare function isCollectionPersistent<Config extends Record<string, CollectionConfig>>(config: Config, collectionName: keyof Config): boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Extract collections that should be stored in a specific file.
|
|
87
|
+
*
|
|
88
|
+
* @param data - Full dataset with all collections
|
|
89
|
+
* @param collectionsForFile - Array of collection names to extract
|
|
90
|
+
* @returns Object containing only the specified collections in object format
|
|
91
|
+
*/
|
|
92
|
+
export declare function extractCollectionsForFile<T extends Record<string, unknown[]>>(data: T, collectionsForFile: readonly string[]): Record<string, Record<string, unknown>>;
|
|
93
|
+
/**
|
|
94
|
+
* Merge file data back into the main dataset.
|
|
95
|
+
* Converts object format back to array format for each collection.
|
|
96
|
+
*
|
|
97
|
+
* @param data - Current dataset to update
|
|
98
|
+
* @param fileData - Data loaded from file (in object format)
|
|
99
|
+
* @param collectionsFromFile - Array of collection names to update
|
|
100
|
+
* @returns Updated dataset with arrays
|
|
101
|
+
*/
|
|
102
|
+
export declare function mergeFileDataIntoDataset<T extends Record<string, unknown[]>>(data: T, fileData: Record<string, Record<string, unknown>>, collectionsFromFile: readonly string[]): T;
|
|
103
|
+
/**
|
|
104
|
+
* Convert an array of entities to a ReadonlyMap keyed by entity ID.
|
|
105
|
+
*
|
|
106
|
+
* @param items - Array of entities, each must have an 'id' field
|
|
107
|
+
* @returns ReadonlyMap keyed by entity id
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* arrayToMap([
|
|
111
|
+
* { id: 'user-1', name: 'Alice' },
|
|
112
|
+
* { id: 'user-2', name: 'Bob' }
|
|
113
|
+
* ])
|
|
114
|
+
* // Returns: Map { 'user-1' => { id: 'user-1', name: 'Alice' }, 'user-2' => { id: 'user-2', name: 'Bob' } }
|
|
115
|
+
*/
|
|
116
|
+
export declare function arrayToMap<T extends {
|
|
117
|
+
readonly id: string;
|
|
118
|
+
}>(items: readonly T[]): ReadonlyMap<string, T>;
|
|
119
|
+
/**
|
|
120
|
+
* Convert a ReadonlyMap to a Record keyed by entity ID (the on-disk object format).
|
|
121
|
+
*
|
|
122
|
+
* @param map - ReadonlyMap of entities keyed by ID
|
|
123
|
+
* @returns Record keyed by entity id
|
|
124
|
+
*
|
|
125
|
+
* @example
|
|
126
|
+
* mapToObject(new Map([
|
|
127
|
+
* ['user-1', { id: 'user-1', name: 'Alice' }],
|
|
128
|
+
* ['user-2', { id: 'user-2', name: 'Bob' }],
|
|
129
|
+
* ]))
|
|
130
|
+
* // Returns: { 'user-1': { id: 'user-1', name: 'Alice' }, 'user-2': { id: 'user-2', name: 'Bob' } }
|
|
131
|
+
*/
|
|
132
|
+
export declare function mapToObject<T>(map: ReadonlyMap<string, T>): Record<string, T>;
|
|
133
|
+
/**
|
|
134
|
+
* Convert a Record keyed by entity ID to a ReadonlyMap.
|
|
135
|
+
* Inverse of mapToObject.
|
|
136
|
+
*
|
|
137
|
+
* @param obj - Record keyed by entity id
|
|
138
|
+
* @returns ReadonlyMap keyed by entity id
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* objectToMap({
|
|
142
|
+
* 'user-1': { id: 'user-1', name: 'Alice' },
|
|
143
|
+
* 'user-2': { id: 'user-2', name: 'Bob' },
|
|
144
|
+
* })
|
|
145
|
+
* // Returns: Map { 'user-1' => { id: 'user-1', name: 'Alice' }, 'user-2' => { id: 'user-2', name: 'Bob' } }
|
|
146
|
+
*/
|
|
147
|
+
export declare function objectToMap<T>(obj: Readonly<Record<string, T>>): ReadonlyMap<string, T>;
|
|
148
|
+
/**
|
|
149
|
+
* Convert a ReadonlyMap to an array of its values.
|
|
150
|
+
*
|
|
151
|
+
* @param map - ReadonlyMap of entities
|
|
152
|
+
* @returns Array of entity values
|
|
153
|
+
*/
|
|
154
|
+
export declare function mapToArray<T>(map: ReadonlyMap<string, T>): readonly T[];
|
|
155
|
+
/**
|
|
156
|
+
* Extract collections from ReadonlyMap-based state for file storage.
|
|
157
|
+
*
|
|
158
|
+
* Takes a Record of collection name → ReadonlyMap and a list of collection
|
|
159
|
+
* names to include, returning nested Record format suitable for serialization.
|
|
160
|
+
*
|
|
161
|
+
* @param stateMaps - Record mapping collection names to their ReadonlyMap state
|
|
162
|
+
* @param collectionsForFile - Collection names to extract
|
|
163
|
+
* @returns Nested Record: { collectionName: { id: entity, ... }, ... }
|
|
164
|
+
*/
|
|
165
|
+
export declare function extractCollectionsFromMaps<T extends {
|
|
166
|
+
readonly id: string;
|
|
167
|
+
}>(stateMaps: Readonly<Record<string, ReadonlyMap<string, T>>>, collectionsForFile: readonly string[]): Record<string, Record<string, T>>;
|
|
168
|
+
/**
|
|
169
|
+
* Merge file data (nested Record format) back into ReadonlyMap-based state.
|
|
170
|
+
*
|
|
171
|
+
* Takes existing state maps, file data in Record format, and collection names,
|
|
172
|
+
* returning updated state maps with the file data merged in.
|
|
173
|
+
*
|
|
174
|
+
* @param stateMaps - Current state: Record of collection name → ReadonlyMap
|
|
175
|
+
* @param fileData - Data from file: { collectionName: { id: entity, ... }, ... }
|
|
176
|
+
* @param collectionsFromFile - Collection names to update from file data
|
|
177
|
+
* @returns Updated state maps
|
|
178
|
+
*/
|
|
179
|
+
export declare function mergeFileDataIntoMaps<T extends {
|
|
180
|
+
readonly id: string;
|
|
181
|
+
}>(stateMaps: Readonly<Record<string, ReadonlyMap<string, T>>>, fileData: Readonly<Record<string, Readonly<Record<string, T>>>>, collectionsFromFile: readonly string[]): Record<string, ReadonlyMap<string, T>>;
|
|
182
|
+
export {};
|
|
183
|
+
//# sourceMappingURL=transforms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transforms.d.ts","sourceRoot":"","sources":["../../src/storage/transforms.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,EACrD,KAAK,EAAE,SAAS,CAAC,EAAE,GACjB,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAanB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAE5D;AAED;;GAEG;AACH,KAAK,gBAAgB,GAAG;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAChC,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAC1E,MAAM,EAAE,MAAM,GACZ,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAcvB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CACjC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAC9C,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAU1B;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CACrC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EAC9C,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,MAAM,GAAG,OAAO,CAKvD;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAC5E,IAAI,EAAE,CAAC,EACP,kBAAkB,EAAE,SAAS,MAAM,EAAE,GACnC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAwBzC;AAED;;;;;;;;GAQG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAC3E,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EACjD,mBAAmB,EAAE,SAAS,MAAM,EAAE,GACpC,CAAC,CAkBH;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EAC3D,KAAK,EAAE,SAAS,CAAC,EAAE,GACjB,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAExB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAM7E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC5B,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,GAC9B,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAExB;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,EAAE,CAEvE;AAED;;;;;;;;;GASG;AACH,wBAAgB,0BAA0B,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EAC3E,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAC3D,kBAAkB,EAAE,SAAS,MAAM,EAAE,GACnC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAWnC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,CAAC,SAAS;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,EACtE,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,EAC3D,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAC/D,mBAAmB,EAAE,SAAS,MAAM,EAAE,GACpC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAWxC"}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data transformation utilities for converting between internal formats
|
|
3
|
+
* (ReadonlyMap and array) and storage object format, plus collection
|
|
4
|
+
* file grouping utilities.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Convert an array of entities with id fields to an object keyed by id.
|
|
8
|
+
* This provides O(1) lookups in storage files.
|
|
9
|
+
*
|
|
10
|
+
* @param items - Array of entities, each must have an 'id' field
|
|
11
|
+
* @returns Object keyed by entity id
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* arrayToObject([
|
|
15
|
+
* { id: 'user-1', name: 'Alice' },
|
|
16
|
+
* { id: 'user-2', name: 'Bob' }
|
|
17
|
+
* ])
|
|
18
|
+
* // Returns: {
|
|
19
|
+
* // 'user-1': { id: 'user-1', name: 'Alice' },
|
|
20
|
+
* // 'user-2': { id: 'user-2', name: 'Bob' }
|
|
21
|
+
* // }
|
|
22
|
+
*/
|
|
23
|
+
export function arrayToObject(items) {
|
|
24
|
+
const result = {};
|
|
25
|
+
for (const item of items) {
|
|
26
|
+
if (typeof item.id !== "string") {
|
|
27
|
+
throw new Error(`Invalid entity: id must be a string, got ${typeof item.id}`);
|
|
28
|
+
}
|
|
29
|
+
result[item.id] = item;
|
|
30
|
+
}
|
|
31
|
+
return result;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Convert an object keyed by id back to an array of entities.
|
|
35
|
+
*
|
|
36
|
+
* @param obj - Object keyed by entity id
|
|
37
|
+
* @returns Array of entities
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* objectToArray({
|
|
41
|
+
* 'user-1': { id: 'user-1', name: 'Alice' },
|
|
42
|
+
* 'user-2': { id: 'user-2', name: 'Bob' }
|
|
43
|
+
* })
|
|
44
|
+
* // Returns: [
|
|
45
|
+
* // { id: 'user-1', name: 'Alice' },
|
|
46
|
+
* // { id: 'user-2', name: 'Bob' }
|
|
47
|
+
* // ]
|
|
48
|
+
*/
|
|
49
|
+
export function objectToArray(obj) {
|
|
50
|
+
return Object.values(obj);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Group collections by their configured file paths.
|
|
54
|
+
* Collections without a file path are not included in the result.
|
|
55
|
+
*
|
|
56
|
+
* @param config - Database configuration with collection definitions
|
|
57
|
+
* @returns Map from file path to array of collection names that use that file
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* groupByFile({
|
|
61
|
+
* users: { schema: UserSchema, file: '/data/users.json' },
|
|
62
|
+
* products: { schema: ProductSchema, file: '/data/db.json' },
|
|
63
|
+
* categories: { schema: CategorySchema, file: '/data/db.json' },
|
|
64
|
+
* sessions: { schema: SessionSchema } // no file = in-memory only
|
|
65
|
+
* })
|
|
66
|
+
* // Returns: Map {
|
|
67
|
+
* // '/data/users.json' => ['users'],
|
|
68
|
+
* // '/data/db.json' => ['products', 'categories']
|
|
69
|
+
* // }
|
|
70
|
+
*/
|
|
71
|
+
export function groupByFile(config) {
|
|
72
|
+
const fileGroups = new Map();
|
|
73
|
+
for (const [collectionName, collectionConfig] of Object.entries(config)) {
|
|
74
|
+
const filePath = collectionConfig.file;
|
|
75
|
+
if (filePath && typeof filePath === "string") {
|
|
76
|
+
const existingCollections = fileGroups.get(filePath) ?? [];
|
|
77
|
+
existingCollections.push(collectionName);
|
|
78
|
+
fileGroups.set(filePath, existingCollections);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return fileGroups;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get all unique file paths from a database configuration.
|
|
85
|
+
*
|
|
86
|
+
* @param config - Database configuration with collection definitions
|
|
87
|
+
* @returns Array of unique file paths used by collections
|
|
88
|
+
*/
|
|
89
|
+
export function getConfigFilePaths(config) {
|
|
90
|
+
const filePaths = new Set();
|
|
91
|
+
for (const collectionConfig of Object.values(config)) {
|
|
92
|
+
if (collectionConfig.file && typeof collectionConfig.file === "string") {
|
|
93
|
+
filePaths.add(collectionConfig.file);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return Array.from(filePaths);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Check if a collection is configured for persistence.
|
|
100
|
+
*
|
|
101
|
+
* @param config - Database configuration
|
|
102
|
+
* @param collectionName - Name of the collection to check
|
|
103
|
+
* @returns True if the collection has a file path configured
|
|
104
|
+
*/
|
|
105
|
+
export function isCollectionPersistent(config, collectionName) {
|
|
106
|
+
const collectionConfig = config[collectionName];
|
|
107
|
+
return !!(collectionConfig?.file && typeof collectionConfig.file === "string");
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Extract collections that should be stored in a specific file.
|
|
111
|
+
*
|
|
112
|
+
* @param data - Full dataset with all collections
|
|
113
|
+
* @param collectionsForFile - Array of collection names to extract
|
|
114
|
+
* @returns Object containing only the specified collections in object format
|
|
115
|
+
*/
|
|
116
|
+
export function extractCollectionsForFile(data, collectionsForFile) {
|
|
117
|
+
const result = {};
|
|
118
|
+
for (const collectionName of collectionsForFile) {
|
|
119
|
+
const collectionData = data[collectionName];
|
|
120
|
+
if (Array.isArray(collectionData)) {
|
|
121
|
+
// Validate that all items have string id fields
|
|
122
|
+
const validItems = collectionData.filter((item) => {
|
|
123
|
+
return (typeof item === "object" &&
|
|
124
|
+
item !== null &&
|
|
125
|
+
"id" in item &&
|
|
126
|
+
typeof item.id === "string");
|
|
127
|
+
});
|
|
128
|
+
result[collectionName] = arrayToObject(validItems);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Merge file data back into the main dataset.
|
|
135
|
+
* Converts object format back to array format for each collection.
|
|
136
|
+
*
|
|
137
|
+
* @param data - Current dataset to update
|
|
138
|
+
* @param fileData - Data loaded from file (in object format)
|
|
139
|
+
* @param collectionsFromFile - Array of collection names to update
|
|
140
|
+
* @returns Updated dataset with arrays
|
|
141
|
+
*/
|
|
142
|
+
export function mergeFileDataIntoDataset(data, fileData, collectionsFromFile) {
|
|
143
|
+
const result = { ...data };
|
|
144
|
+
for (const collectionName of collectionsFromFile) {
|
|
145
|
+
const collectionFileData = fileData[collectionName];
|
|
146
|
+
if (collectionFileData && typeof collectionFileData === "object") {
|
|
147
|
+
// Convert back to array format
|
|
148
|
+
const arrayData = objectToArray(collectionFileData);
|
|
149
|
+
// Type-safe assignment using index signature constraint
|
|
150
|
+
if (collectionName in result) {
|
|
151
|
+
result[collectionName] = arrayData;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
// ============================================================================
|
|
158
|
+
// ReadonlyMap-aware transforms (Effect migration)
|
|
159
|
+
// ============================================================================
|
|
160
|
+
/**
|
|
161
|
+
* Convert an array of entities to a ReadonlyMap keyed by entity ID.
|
|
162
|
+
*
|
|
163
|
+
* @param items - Array of entities, each must have an 'id' field
|
|
164
|
+
* @returns ReadonlyMap keyed by entity id
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* arrayToMap([
|
|
168
|
+
* { id: 'user-1', name: 'Alice' },
|
|
169
|
+
* { id: 'user-2', name: 'Bob' }
|
|
170
|
+
* ])
|
|
171
|
+
* // Returns: Map { 'user-1' => { id: 'user-1', name: 'Alice' }, 'user-2' => { id: 'user-2', name: 'Bob' } }
|
|
172
|
+
*/
|
|
173
|
+
export function arrayToMap(items) {
|
|
174
|
+
return new Map(items.map((item) => [item.id, item]));
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Convert a ReadonlyMap to a Record keyed by entity ID (the on-disk object format).
|
|
178
|
+
*
|
|
179
|
+
* @param map - ReadonlyMap of entities keyed by ID
|
|
180
|
+
* @returns Record keyed by entity id
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* mapToObject(new Map([
|
|
184
|
+
* ['user-1', { id: 'user-1', name: 'Alice' }],
|
|
185
|
+
* ['user-2', { id: 'user-2', name: 'Bob' }],
|
|
186
|
+
* ]))
|
|
187
|
+
* // Returns: { 'user-1': { id: 'user-1', name: 'Alice' }, 'user-2': { id: 'user-2', name: 'Bob' } }
|
|
188
|
+
*/
|
|
189
|
+
export function mapToObject(map) {
|
|
190
|
+
const result = {};
|
|
191
|
+
for (const [key, value] of map) {
|
|
192
|
+
result[key] = value;
|
|
193
|
+
}
|
|
194
|
+
return result;
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Convert a Record keyed by entity ID to a ReadonlyMap.
|
|
198
|
+
* Inverse of mapToObject.
|
|
199
|
+
*
|
|
200
|
+
* @param obj - Record keyed by entity id
|
|
201
|
+
* @returns ReadonlyMap keyed by entity id
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* objectToMap({
|
|
205
|
+
* 'user-1': { id: 'user-1', name: 'Alice' },
|
|
206
|
+
* 'user-2': { id: 'user-2', name: 'Bob' },
|
|
207
|
+
* })
|
|
208
|
+
* // Returns: Map { 'user-1' => { id: 'user-1', name: 'Alice' }, 'user-2' => { id: 'user-2', name: 'Bob' } }
|
|
209
|
+
*/
|
|
210
|
+
export function objectToMap(obj) {
|
|
211
|
+
return new Map(Object.entries(obj));
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Convert a ReadonlyMap to an array of its values.
|
|
215
|
+
*
|
|
216
|
+
* @param map - ReadonlyMap of entities
|
|
217
|
+
* @returns Array of entity values
|
|
218
|
+
*/
|
|
219
|
+
export function mapToArray(map) {
|
|
220
|
+
return Array.from(map.values());
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Extract collections from ReadonlyMap-based state for file storage.
|
|
224
|
+
*
|
|
225
|
+
* Takes a Record of collection name → ReadonlyMap and a list of collection
|
|
226
|
+
* names to include, returning nested Record format suitable for serialization.
|
|
227
|
+
*
|
|
228
|
+
* @param stateMaps - Record mapping collection names to their ReadonlyMap state
|
|
229
|
+
* @param collectionsForFile - Collection names to extract
|
|
230
|
+
* @returns Nested Record: { collectionName: { id: entity, ... }, ... }
|
|
231
|
+
*/
|
|
232
|
+
export function extractCollectionsFromMaps(stateMaps, collectionsForFile) {
|
|
233
|
+
const result = {};
|
|
234
|
+
for (const collectionName of collectionsForFile) {
|
|
235
|
+
const collectionMap = stateMaps[collectionName];
|
|
236
|
+
if (collectionMap !== undefined) {
|
|
237
|
+
result[collectionName] = mapToObject(collectionMap);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Merge file data (nested Record format) back into ReadonlyMap-based state.
|
|
244
|
+
*
|
|
245
|
+
* Takes existing state maps, file data in Record format, and collection names,
|
|
246
|
+
* returning updated state maps with the file data merged in.
|
|
247
|
+
*
|
|
248
|
+
* @param stateMaps - Current state: Record of collection name → ReadonlyMap
|
|
249
|
+
* @param fileData - Data from file: { collectionName: { id: entity, ... }, ... }
|
|
250
|
+
* @param collectionsFromFile - Collection names to update from file data
|
|
251
|
+
* @returns Updated state maps
|
|
252
|
+
*/
|
|
253
|
+
export function mergeFileDataIntoMaps(stateMaps, fileData, collectionsFromFile) {
|
|
254
|
+
const result = { ...stateMaps };
|
|
255
|
+
for (const collectionName of collectionsFromFile) {
|
|
256
|
+
const collectionFileData = fileData[collectionName];
|
|
257
|
+
if (collectionFileData !== undefined) {
|
|
258
|
+
result[collectionName] = objectToMap(collectionFileData);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return result;
|
|
262
|
+
}
|
|
263
|
+
//# sourceMappingURL=transforms.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transforms.js","sourceRoot":"","sources":["../../src/storage/transforms.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
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
|
+
import type { EffectCollection } from "../factories/database-effect.js";
|
|
15
|
+
import type { TransactionContext } from "../types/crud-types.js";
|
|
16
|
+
import type { ChangeEvent } from "../types/reactive-types.js";
|
|
17
|
+
type HasId = {
|
|
18
|
+
readonly id: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Internal ref map type used for cross-collection references.
|
|
22
|
+
*/
|
|
23
|
+
type StateRefs = Record<string, Ref.Ref<ReadonlyMap<string, HasId>>>;
|
|
24
|
+
/**
|
|
25
|
+
* Persistence trigger interface for scheduling debounced saves.
|
|
26
|
+
*/
|
|
27
|
+
interface PersistenceTrigger {
|
|
28
|
+
/** Schedule a debounced save for the given key */
|
|
29
|
+
readonly schedule: (key: string) => void;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Callback type for building a collection with transaction-aware afterMutation.
|
|
33
|
+
* The afterMutation adds the collection name to the mutation set instead of
|
|
34
|
+
* scheduling a persistence write.
|
|
35
|
+
*/
|
|
36
|
+
type BuildCollectionForTx = (collectionName: string, addMutation: (name: string) => void) => EffectCollection<HasId>;
|
|
37
|
+
/**
|
|
38
|
+
* Create a new transaction context.
|
|
39
|
+
*
|
|
40
|
+
* Parameters:
|
|
41
|
+
* - stateRefs: The database's collection Refs (will be snapshotted and potentially restored)
|
|
42
|
+
* - transactionLock: Single-writer lock Ref (prevents concurrent transactions)
|
|
43
|
+
* - buildCollectionForTx: Callback to create collection accessors with transaction-aware mutations
|
|
44
|
+
* - persistenceTrigger: Optional trigger for scheduling saves on commit
|
|
45
|
+
* - changePubSub: Optional PubSub for reactive change notifications. When provided,
|
|
46
|
+
* individual mutation events are suppressed during the transaction and a single
|
|
47
|
+
* batch event is published for each mutated collection on commit.
|
|
48
|
+
*
|
|
49
|
+
* Returns an Effect that yields a TransactionContext. The context provides:
|
|
50
|
+
* - Collection accessors with the same interface as db.collectionName
|
|
51
|
+
* - commit() to finalize changes and trigger persistence
|
|
52
|
+
* - rollback() to restore snapshots and discard changes
|
|
53
|
+
* - isActive to check if transaction is still open
|
|
54
|
+
* - mutatedCollections to see which collections were written to
|
|
55
|
+
*
|
|
56
|
+
* On failure (e.g., lock already held), returns TransactionError.
|
|
57
|
+
*/
|
|
58
|
+
export declare const createTransaction: <DB extends Record<string, EffectCollection<HasId>>>(stateRefs: StateRefs, transactionLock: Ref.Ref<boolean>, buildCollectionForTx: BuildCollectionForTx, persistenceTrigger?: PersistenceTrigger, changePubSub?: PubSub.PubSub<ChangeEvent>) => Effect.Effect<TransactionContext<DB>, TransactionError>;
|
|
59
|
+
/**
|
|
60
|
+
* Execute a callback within an atomic transaction context.
|
|
61
|
+
*
|
|
62
|
+
* All CRUD operations inside the callback operate against the live in-memory state.
|
|
63
|
+
* On success, changes are committed and persistence is triggered.
|
|
64
|
+
* On failure (error thrown or explicit rollback), all mutations are reverted.
|
|
65
|
+
*
|
|
66
|
+
* Usage:
|
|
67
|
+
* ```ts
|
|
68
|
+
* const result = await db.$transaction((ctx) =>
|
|
69
|
+
* Effect.gen(function* () {
|
|
70
|
+
* const user = yield* ctx.users.create({ name: "Alice" })
|
|
71
|
+
* const post = yield* ctx.posts.create({ authorId: user.id, title: "Hello" })
|
|
72
|
+
* return { user, post }
|
|
73
|
+
* })
|
|
74
|
+
* ).pipe(Effect.runPromise)
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @param stateRefs - The database's collection Refs
|
|
78
|
+
* @param transactionLock - Single-writer lock Ref
|
|
79
|
+
* @param buildCollectionForTx - Callback to create collection accessors
|
|
80
|
+
* @param persistenceTrigger - Optional trigger for scheduling saves on commit
|
|
81
|
+
* @param changePubSub - Optional PubSub for reactive change notifications
|
|
82
|
+
* @param fn - The callback to execute within the transaction
|
|
83
|
+
* @returns Effect that yields the callback result, with TransactionError in error channel
|
|
84
|
+
*/
|
|
85
|
+
export declare const $transaction: <DB extends Record<string, EffectCollection<HasId>>, A, E>(stateRefs: StateRefs, transactionLock: Ref.Ref<boolean>, buildCollectionForTx: BuildCollectionForTx, persistenceTrigger: PersistenceTrigger | undefined, changePubSub: PubSub.PubSub<ChangeEvent> | undefined, fn: (ctx: TransactionContext<DB>) => Effect.Effect<A, E>) => Effect.Effect<A, E | TransactionError>;
|
|
86
|
+
export {};
|
|
87
|
+
//# sourceMappingURL=transaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transaction.d.ts","sourceRoot":"","sources":["../../src/transactions/transaction.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAM9D,KAAK,KAAK,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC;;GAEG;AACH,KAAK,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AAErE;;GAEG;AACH,UAAU,kBAAkB;IAC3B,kDAAkD;IAClD,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACzC;AAED;;;;GAIG;AACH,KAAK,oBAAoB,GAAG,CAC3B,cAAc,EAAE,MAAM,EACtB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAC/B,gBAAgB,CAAC,KAAK,CAAC,CAAC;AAM7B;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,iBAAiB,GAC7B,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAElD,WAAW,SAAS,EACpB,iBAAiB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,EACjC,sBAAsB,oBAAoB,EAC1C,qBAAqB,kBAAkB,EACvC,eAAe,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,KACvC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,EAAE,CAAC,EAAE,gBAAgB,CAwLtD,CAAC;AAMJ;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,YAAY,GACxB,EAAE,SAAS,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAClD,CAAC,EACD,CAAC,EAED,WAAW,SAAS,EACpB,iBAAiB,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,EACjC,sBAAsB,oBAAoB,EAC1C,oBAAoB,kBAAkB,GAAG,SAAS,EAClD,cAAc,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,SAAS,EACpD,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KACtD,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,gBAAgB,CAgDrC,CAAC"}
|