@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,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory functions for creating ChangeEvent objects.
|
|
3
|
+
*
|
|
4
|
+
* These functions provide a convenient and type-safe way to create change events
|
|
5
|
+
* that are published by CRUD operations and file watchers to notify reactive subscriptions.
|
|
6
|
+
*/
|
|
7
|
+
import type { ChangeEvent } from "../types/reactive-types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Creates a ChangeEvent for a collection mutation.
|
|
10
|
+
*
|
|
11
|
+
* @param collection - The name of the collection that was modified
|
|
12
|
+
* @param operation - The type of mutation: "create", "update", "delete", or "reload"
|
|
13
|
+
* @returns A ChangeEvent object
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* // After creating an entity
|
|
18
|
+
* const event = createChangeEvent("books", "create")
|
|
19
|
+
* yield* PubSub.publish(pubsub, event)
|
|
20
|
+
*
|
|
21
|
+
* // After updating an entity
|
|
22
|
+
* const event = createChangeEvent("books", "update")
|
|
23
|
+
* yield* PubSub.publish(pubsub, event)
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare const createChangeEvent: (collection: string, operation: ChangeEvent["operation"]) => ChangeEvent;
|
|
27
|
+
/**
|
|
28
|
+
* Creates a ChangeEvent for a file watcher reload.
|
|
29
|
+
*
|
|
30
|
+
* This is a convenience function for the common case of creating
|
|
31
|
+
* a reload event after data is reloaded from disk.
|
|
32
|
+
*
|
|
33
|
+
* @param collection - The name of the collection that was reloaded
|
|
34
|
+
* @returns A ChangeEvent with operation: "reload"
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* // After reloading data from disk
|
|
39
|
+
* const event = reloadEvent("books")
|
|
40
|
+
* yield* PubSub.publish(pubsub, event)
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
export declare const reloadEvent: (collection: string) => ChangeEvent;
|
|
44
|
+
//# sourceMappingURL=change-event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-event.d.ts","sourceRoot":"","sources":["../../src/reactive/change-event.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,iBAAiB,GAC7B,YAAY,MAAM,EAClB,WAAW,WAAW,CAAC,WAAW,CAAC,KACjC,WAGD,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,WAAW,GAAI,YAAY,MAAM,KAAG,WAG/C,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Factory functions for creating ChangeEvent objects.
|
|
3
|
+
*
|
|
4
|
+
* These functions provide a convenient and type-safe way to create change events
|
|
5
|
+
* that are published by CRUD operations and file watchers to notify reactive subscriptions.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Creates a ChangeEvent for a collection mutation.
|
|
9
|
+
*
|
|
10
|
+
* @param collection - The name of the collection that was modified
|
|
11
|
+
* @param operation - The type of mutation: "create", "update", "delete", or "reload"
|
|
12
|
+
* @returns A ChangeEvent object
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* // After creating an entity
|
|
17
|
+
* const event = createChangeEvent("books", "create")
|
|
18
|
+
* yield* PubSub.publish(pubsub, event)
|
|
19
|
+
*
|
|
20
|
+
* // After updating an entity
|
|
21
|
+
* const event = createChangeEvent("books", "update")
|
|
22
|
+
* yield* PubSub.publish(pubsub, event)
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export const createChangeEvent = (collection, operation) => ({
|
|
26
|
+
collection,
|
|
27
|
+
operation,
|
|
28
|
+
});
|
|
29
|
+
/**
|
|
30
|
+
* Creates a ChangeEvent for a file watcher reload.
|
|
31
|
+
*
|
|
32
|
+
* This is a convenience function for the common case of creating
|
|
33
|
+
* a reload event after data is reloaded from disk.
|
|
34
|
+
*
|
|
35
|
+
* @param collection - The name of the collection that was reloaded
|
|
36
|
+
* @returns A ChangeEvent with operation: "reload"
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* // After reloading data from disk
|
|
41
|
+
* const event = reloadEvent("books")
|
|
42
|
+
* yield* PubSub.publish(pubsub, event)
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export const reloadEvent = (collection) => ({
|
|
46
|
+
collection,
|
|
47
|
+
operation: "reload",
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=change-event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-event.js","sourceRoot":"","sources":["../../src/reactive/change-event.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAChC,UAAkB,EAClB,SAAmC,EACrB,EAAE,CAAC,CAAC;IAClB,UAAU;IACV,SAAS;CACT,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,UAAkB,EAAe,EAAE,CAAC,CAAC;IAChE,UAAU;IACV,SAAS,EAAE,QAAQ;CACnB,CAAC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PubSub for broadcasting change events to reactive query subscribers.
|
|
3
|
+
*
|
|
4
|
+
* Uses Effect's unbounded PubSub to ensure all change events are delivered
|
|
5
|
+
* to subscribers - dropping events would break subscription correctness.
|
|
6
|
+
*/
|
|
7
|
+
import { type Effect, PubSub } from "effect";
|
|
8
|
+
import type { ChangeEvent } from "../types/reactive-types.js";
|
|
9
|
+
/**
|
|
10
|
+
* Creates an unbounded PubSub for broadcasting ChangeEvents.
|
|
11
|
+
*
|
|
12
|
+
* The PubSub is unbounded because:
|
|
13
|
+
* - Dropping change events would cause subscriptions to miss mutations
|
|
14
|
+
* - This could lead to stale result sets being displayed
|
|
15
|
+
* - Back-pressure is handled by debouncing at the subscription level
|
|
16
|
+
*
|
|
17
|
+
* @returns Effect that produces a PubSub for ChangeEvents
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const program = Effect.gen(function* () {
|
|
22
|
+
* const pubsub = yield* createChangePubSub()
|
|
23
|
+
* // Publishers can publish events
|
|
24
|
+
* yield* pubsub.publish({ collection: "books", operation: "create" })
|
|
25
|
+
* // Subscribers receive events via subscription queues
|
|
26
|
+
* const subscription = yield* pubsub.subscribe
|
|
27
|
+
* const event = yield* Queue.take(subscription)
|
|
28
|
+
* })
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare const createChangePubSub: () => Effect.Effect<PubSub.PubSub<ChangeEvent>>;
|
|
32
|
+
//# sourceMappingURL=change-pubsub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-pubsub.d.ts","sourceRoot":"","sources":["../../src/reactive/change-pubsub.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,kBAAkB,QAAO,MAAM,CAAC,MAAM,CAClD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CACS,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PubSub for broadcasting change events to reactive query subscribers.
|
|
3
|
+
*
|
|
4
|
+
* Uses Effect's unbounded PubSub to ensure all change events are delivered
|
|
5
|
+
* to subscribers - dropping events would break subscription correctness.
|
|
6
|
+
*/
|
|
7
|
+
import { PubSub } from "effect";
|
|
8
|
+
/**
|
|
9
|
+
* Creates an unbounded PubSub for broadcasting ChangeEvents.
|
|
10
|
+
*
|
|
11
|
+
* The PubSub is unbounded because:
|
|
12
|
+
* - Dropping change events would cause subscriptions to miss mutations
|
|
13
|
+
* - This could lead to stale result sets being displayed
|
|
14
|
+
* - Back-pressure is handled by debouncing at the subscription level
|
|
15
|
+
*
|
|
16
|
+
* @returns Effect that produces a PubSub for ChangeEvents
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* const program = Effect.gen(function* () {
|
|
21
|
+
* const pubsub = yield* createChangePubSub()
|
|
22
|
+
* // Publishers can publish events
|
|
23
|
+
* yield* pubsub.publish({ collection: "books", operation: "create" })
|
|
24
|
+
* // Subscribers receive events via subscription queues
|
|
25
|
+
* const subscription = yield* pubsub.subscribe
|
|
26
|
+
* const event = yield* Queue.take(subscription)
|
|
27
|
+
* })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export const createChangePubSub = () => PubSub.unbounded();
|
|
31
|
+
//# sourceMappingURL=change-pubsub.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"change-pubsub.js","sourceRoot":"","sources":["../../src/reactive/change-pubsub.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAe,MAAM,EAAE,MAAM,QAAQ,CAAC;AAG7C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAEhC,EAAE,CAAC,MAAM,CAAC,SAAS,EAAe,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reusable query evaluation function for reactive queries.
|
|
3
|
+
*
|
|
4
|
+
* Reads the current state from a Ref and applies the query pipeline
|
|
5
|
+
* (filter, sort, select, paginate) to produce a result array.
|
|
6
|
+
*
|
|
7
|
+
* Used by watch() for initial emission and re-evaluation on change events.
|
|
8
|
+
*/
|
|
9
|
+
import { Effect, Ref } from "effect";
|
|
10
|
+
/**
|
|
11
|
+
* Configuration for query evaluation.
|
|
12
|
+
* Mirrors the subset of QueryConfig that applies to reactive queries.
|
|
13
|
+
*/
|
|
14
|
+
export interface EvaluateQueryConfig {
|
|
15
|
+
readonly where?: Record<string, unknown>;
|
|
16
|
+
readonly sort?: Record<string, "asc" | "desc">;
|
|
17
|
+
readonly select?: Record<string, unknown> | ReadonlyArray<string>;
|
|
18
|
+
readonly limit?: number;
|
|
19
|
+
readonly offset?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Entity constraint: must have a readonly string `id` field.
|
|
23
|
+
*/
|
|
24
|
+
type HasId = {
|
|
25
|
+
readonly id: string;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Evaluates a query against the current state in the Ref.
|
|
29
|
+
*
|
|
30
|
+
* Reads all entities from the Ref, applies the query pipeline (filter, sort,
|
|
31
|
+
* select, paginate), and returns the result as a ReadonlyArray.
|
|
32
|
+
*
|
|
33
|
+
* This is a pure function that:
|
|
34
|
+
* - Does NOT emit multiple values over time (unlike a Stream)
|
|
35
|
+
* - Does NOT provide cursor-based pagination (returns complete result snapshot)
|
|
36
|
+
* - Returns the entire result set as a single ReadonlyArray
|
|
37
|
+
*
|
|
38
|
+
* @param ref - The collection Ref containing entities keyed by ID
|
|
39
|
+
* @param config - Query configuration (where, sort, select, limit, offset)
|
|
40
|
+
* @returns Effect producing the query result as a ReadonlyArray
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```ts
|
|
44
|
+
* const program = Effect.gen(function* () {
|
|
45
|
+
* const ref = yield* createCollectionState<Book>([
|
|
46
|
+
* { id: "1", title: "Dune", year: 1965, genre: "sci-fi" },
|
|
47
|
+
* { id: "2", title: "Neuromancer", year: 1984, genre: "sci-fi" },
|
|
48
|
+
* { id: "3", title: "The Hobbit", year: 1937, genre: "fantasy" },
|
|
49
|
+
* ])
|
|
50
|
+
*
|
|
51
|
+
* const results = yield* evaluateQuery(ref, {
|
|
52
|
+
* where: { genre: "sci-fi" },
|
|
53
|
+
* sort: { year: "desc" },
|
|
54
|
+
* limit: 1,
|
|
55
|
+
* })
|
|
56
|
+
* // results: [{ id: "2", title: "Neuromancer", year: 1984, genre: "sci-fi" }]
|
|
57
|
+
* })
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export declare const evaluateQuery: <T extends HasId>(ref: Ref.Ref<ReadonlyMap<string, T>>, config?: EvaluateQueryConfig) => Effect.Effect<ReadonlyArray<T>>;
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=evaluate-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluate-query.d.ts","sourceRoot":"","sources":["../../src/reactive/evaluate-query.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,GAAG,EAAU,MAAM,QAAQ,CAAC;AAM7C;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC,CAAC;IAC/C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IAClE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,KAAK,KAAK,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,KAAK,EAC5C,KAAK,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EACpC,SAAQ,mBAAwB,KAC9B,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAiB9B,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reusable query evaluation function for reactive queries.
|
|
3
|
+
*
|
|
4
|
+
* Reads the current state from a Ref and applies the query pipeline
|
|
5
|
+
* (filter, sort, select, paginate) to produce a result array.
|
|
6
|
+
*
|
|
7
|
+
* Used by watch() for initial emission and re-evaluation on change events.
|
|
8
|
+
*/
|
|
9
|
+
import { Effect, Ref, Stream } from "effect";
|
|
10
|
+
import { applyFilter } from "../operations/query/filter-stream.js";
|
|
11
|
+
import { applyPagination } from "../operations/query/paginate-stream.js";
|
|
12
|
+
import { applySelect } from "../operations/query/select-stream.js";
|
|
13
|
+
import { applySort } from "../operations/query/sort-stream.js";
|
|
14
|
+
/**
|
|
15
|
+
* Evaluates a query against the current state in the Ref.
|
|
16
|
+
*
|
|
17
|
+
* Reads all entities from the Ref, applies the query pipeline (filter, sort,
|
|
18
|
+
* select, paginate), and returns the result as a ReadonlyArray.
|
|
19
|
+
*
|
|
20
|
+
* This is a pure function that:
|
|
21
|
+
* - Does NOT emit multiple values over time (unlike a Stream)
|
|
22
|
+
* - Does NOT provide cursor-based pagination (returns complete result snapshot)
|
|
23
|
+
* - Returns the entire result set as a single ReadonlyArray
|
|
24
|
+
*
|
|
25
|
+
* @param ref - The collection Ref containing entities keyed by ID
|
|
26
|
+
* @param config - Query configuration (where, sort, select, limit, offset)
|
|
27
|
+
* @returns Effect producing the query result as a ReadonlyArray
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const program = Effect.gen(function* () {
|
|
32
|
+
* const ref = yield* createCollectionState<Book>([
|
|
33
|
+
* { id: "1", title: "Dune", year: 1965, genre: "sci-fi" },
|
|
34
|
+
* { id: "2", title: "Neuromancer", year: 1984, genre: "sci-fi" },
|
|
35
|
+
* { id: "3", title: "The Hobbit", year: 1937, genre: "fantasy" },
|
|
36
|
+
* ])
|
|
37
|
+
*
|
|
38
|
+
* const results = yield* evaluateQuery(ref, {
|
|
39
|
+
* where: { genre: "sci-fi" },
|
|
40
|
+
* sort: { year: "desc" },
|
|
41
|
+
* limit: 1,
|
|
42
|
+
* })
|
|
43
|
+
* // results: [{ id: "2", title: "Neuromancer", year: 1984, genre: "sci-fi" }]
|
|
44
|
+
* })
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export const evaluateQuery = (ref, config = {}) => Effect.gen(function* () {
|
|
48
|
+
// Read current state from Ref
|
|
49
|
+
const map = yield* Ref.get(ref);
|
|
50
|
+
const entities = Array.from(map.values());
|
|
51
|
+
// Build and execute the query pipeline
|
|
52
|
+
const stream = Stream.fromIterable(entities).pipe(applyFilter(config.where), applySort(config.sort), applyPagination(config.offset, config.limit), applySelect(config.select));
|
|
53
|
+
// Collect results into an array
|
|
54
|
+
const chunk = yield* Stream.runCollect(stream);
|
|
55
|
+
return Array.from(chunk);
|
|
56
|
+
});
|
|
57
|
+
//# sourceMappingURL=evaluate-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluate-query.js","sourceRoot":"","sources":["../../src/reactive/evaluate-query.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,MAAM,oCAAoC,CAAC;AAmB/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC5B,GAAoC,EACpC,SAA8B,EAAE,EACE,EAAE,CACpC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IACnB,8BAA8B;IAC9B,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;IAE1C,uCAAuC;IACvC,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,IAAI,CAChD,WAAW,CAAC,MAAM,CAAC,KAAK,CAAC,EACzB,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,EACtB,eAAe,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,EAC5C,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,CAC1B,CAAC;IAEF,gCAAgC;IAChC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC/C,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAqB,CAAC;AAC9C,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* watchById() implementation for reactive single-entity queries.
|
|
3
|
+
*
|
|
4
|
+
* Thin wrapper over watch() that filters by ID and maps results to T | null.
|
|
5
|
+
* Emits the entity when it exists, or null when it's deleted or doesn't exist.
|
|
6
|
+
*/
|
|
7
|
+
import { Effect, type PubSub, type Ref, Stream } from "effect";
|
|
8
|
+
import type { ChangeEvent } from "../types/reactive-types.js";
|
|
9
|
+
import { type WatchQueryConfig } from "./watch.js";
|
|
10
|
+
/**
|
|
11
|
+
* Entity constraint: must have a readonly string `id` field.
|
|
12
|
+
*/
|
|
13
|
+
type HasId = {
|
|
14
|
+
readonly id: string;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Creates a reactive watch stream for a single entity by ID.
|
|
18
|
+
*
|
|
19
|
+
* This is a thin wrapper over watch() that:
|
|
20
|
+
* 1. Filters by `where: { id }` to only match the specific entity
|
|
21
|
+
* 2. Maps the result array to `T | null` (first element or null if empty)
|
|
22
|
+
*
|
|
23
|
+
* The stream:
|
|
24
|
+
* - Emits the entity immediately if it exists, or null if not
|
|
25
|
+
* - Re-emits when the entity is created, updated, or deleted
|
|
26
|
+
* - Emits null when the entity is deleted (result array becomes empty)
|
|
27
|
+
* - Is scoped: auto-cleanup when scope closes or stream is interrupted
|
|
28
|
+
*
|
|
29
|
+
* @param pubsub - The PubSub broadcasting ChangeEvents from mutations
|
|
30
|
+
* @param ref - The collection Ref containing entities keyed by ID
|
|
31
|
+
* @param collectionName - Name of the collection to watch (for filtering events)
|
|
32
|
+
* @param id - The entity ID to watch
|
|
33
|
+
* @param config - Optional additional watch configuration (debounceMs)
|
|
34
|
+
* @returns Scoped Effect producing a Stream of T | null
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* const program = Effect.gen(function* () {
|
|
39
|
+
* const pubsub = yield* createChangePubSub()
|
|
40
|
+
* const ref = yield* createCollectionState<Book>([
|
|
41
|
+
* { id: "1", title: "Dune", author: "Frank Herbert" }
|
|
42
|
+
* ])
|
|
43
|
+
*
|
|
44
|
+
* const stream = yield* watchById(pubsub, ref, "books", "1")
|
|
45
|
+
*
|
|
46
|
+
* // Emits: { id: "1", title: "Dune", author: "Frank Herbert" }
|
|
47
|
+
* // After delete: emits null
|
|
48
|
+
* }).pipe(Effect.scoped)
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare const watchById: <T extends HasId>(pubsub: PubSub.PubSub<ChangeEvent>, ref: Ref.Ref<ReadonlyMap<string, T>>, collectionName: string, id: string, config?: Pick<WatchQueryConfig, "debounceMs">) => Effect.Effect<Stream.Stream<T | null>, never, import("effect").Scope.Scope>;
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=watch-by-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch-by-id.d.ts","sourceRoot":"","sources":["../../src/reactive/watch-by-id.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,KAAK,MAAM,EAAE,KAAK,GAAG,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC/D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,KAAK,gBAAgB,EAAS,MAAM,YAAY,CAAC;AAE1D;;GAEG;AACH,KAAK,KAAK,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,KAAK,EACxC,QAAQ,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAClC,KAAK,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EACpC,gBAAgB,MAAM,EACtB,IAAI,MAAM,EACV,SAAQ,IAAI,CAAC,gBAAgB,EAAE,YAAY,CAAM,KAC/C,MAAM,CAAC,MAAM,CACf,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,EACvB,KAAK,EACL,OAAO,QAAQ,EAAE,KAAK,CAAC,KAAK,CAa1B,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* watchById() implementation for reactive single-entity queries.
|
|
3
|
+
*
|
|
4
|
+
* Thin wrapper over watch() that filters by ID and maps results to T | null.
|
|
5
|
+
* Emits the entity when it exists, or null when it's deleted or doesn't exist.
|
|
6
|
+
*/
|
|
7
|
+
import { Effect, Stream } from "effect";
|
|
8
|
+
import { watch } from "./watch.js";
|
|
9
|
+
/**
|
|
10
|
+
* Creates a reactive watch stream for a single entity by ID.
|
|
11
|
+
*
|
|
12
|
+
* This is a thin wrapper over watch() that:
|
|
13
|
+
* 1. Filters by `where: { id }` to only match the specific entity
|
|
14
|
+
* 2. Maps the result array to `T | null` (first element or null if empty)
|
|
15
|
+
*
|
|
16
|
+
* The stream:
|
|
17
|
+
* - Emits the entity immediately if it exists, or null if not
|
|
18
|
+
* - Re-emits when the entity is created, updated, or deleted
|
|
19
|
+
* - Emits null when the entity is deleted (result array becomes empty)
|
|
20
|
+
* - Is scoped: auto-cleanup when scope closes or stream is interrupted
|
|
21
|
+
*
|
|
22
|
+
* @param pubsub - The PubSub broadcasting ChangeEvents from mutations
|
|
23
|
+
* @param ref - The collection Ref containing entities keyed by ID
|
|
24
|
+
* @param collectionName - Name of the collection to watch (for filtering events)
|
|
25
|
+
* @param id - The entity ID to watch
|
|
26
|
+
* @param config - Optional additional watch configuration (debounceMs)
|
|
27
|
+
* @returns Scoped Effect producing a Stream of T | null
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* const program = Effect.gen(function* () {
|
|
32
|
+
* const pubsub = yield* createChangePubSub()
|
|
33
|
+
* const ref = yield* createCollectionState<Book>([
|
|
34
|
+
* { id: "1", title: "Dune", author: "Frank Herbert" }
|
|
35
|
+
* ])
|
|
36
|
+
*
|
|
37
|
+
* const stream = yield* watchById(pubsub, ref, "books", "1")
|
|
38
|
+
*
|
|
39
|
+
* // Emits: { id: "1", title: "Dune", author: "Frank Herbert" }
|
|
40
|
+
* // After delete: emits null
|
|
41
|
+
* }).pipe(Effect.scoped)
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export const watchById = (pubsub, ref, collectionName, id, config = {}) => Effect.gen(function* () {
|
|
45
|
+
// Use watch() with a where clause filtering by ID
|
|
46
|
+
const watchStream = yield* watch(pubsub, ref, collectionName, {
|
|
47
|
+
...config,
|
|
48
|
+
where: { id },
|
|
49
|
+
});
|
|
50
|
+
// Map the result array to T | null
|
|
51
|
+
// - results[0] when the entity exists
|
|
52
|
+
// - null when the entity is deleted or doesn't exist
|
|
53
|
+
return Stream.map(watchStream, (results) => results[0] ?? null);
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=watch-by-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch-by-id.js","sourceRoot":"","sources":["../../src/reactive/watch-by-id.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAyB,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE/D,OAAO,EAAyB,KAAK,EAAE,MAAM,YAAY,CAAC;AAO1D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CACxB,MAAkC,EAClC,GAAoC,EACpC,cAAsB,EACtB,EAAU,EACV,SAA+C,EAAE,EAKhD,EAAE,CACH,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IACnB,kDAAkD;IAClD,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE;QAC7D,GAAG,MAAM;QACT,KAAK,EAAE,EAAE,EAAE,EAAE;KACb,CAAC,CAAC;IAEH,mCAAmC;IACnC,sCAAsC;IACtC,qDAAqD;IACrD,OAAO,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;AACjE,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core watch() implementation for reactive queries.
|
|
3
|
+
*
|
|
4
|
+
* Creates a Stream that emits result sets whenever the underlying collection data changes.
|
|
5
|
+
* Subscribes to the PubSub for change notifications, filters events by collection name,
|
|
6
|
+
* re-evaluates the query pipeline on each change, deduplicates identical consecutive results,
|
|
7
|
+
* and emits the new result set.
|
|
8
|
+
*/
|
|
9
|
+
import { Effect, PubSub, type Ref, Scope, Stream } from "effect";
|
|
10
|
+
import type { ChangeEvent } from "../types/reactive-types.js";
|
|
11
|
+
import { type EvaluateQueryConfig } from "./evaluate-query.js";
|
|
12
|
+
/**
|
|
13
|
+
* Configuration for the watch query.
|
|
14
|
+
* Extends EvaluateQueryConfig with debounce options.
|
|
15
|
+
*/
|
|
16
|
+
export interface WatchQueryConfig extends EvaluateQueryConfig {
|
|
17
|
+
/**
|
|
18
|
+
* Debounce interval in milliseconds for change event processing.
|
|
19
|
+
* When multiple mutations occur in rapid succession, they are coalesced
|
|
20
|
+
* into a single re-evaluation after the debounce interval settles.
|
|
21
|
+
* Default: 10ms (fast enough for interactive use, long enough to batch bursts).
|
|
22
|
+
*/
|
|
23
|
+
readonly debounceMs?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Entity constraint: must have a readonly string `id` field.
|
|
27
|
+
*/
|
|
28
|
+
type HasId = {
|
|
29
|
+
readonly id: string;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Creates a reactive watch stream that emits query results whenever the collection changes.
|
|
33
|
+
*
|
|
34
|
+
* The stream:
|
|
35
|
+
* 1. Emits the current result set immediately upon subscription
|
|
36
|
+
* 2. Subscribes to the PubSub for change notifications (scoped - auto-cleanup)
|
|
37
|
+
* 3. Filters events to only those matching the specified collection
|
|
38
|
+
* 4. Debounces change events to coalesce rapid mutations into single re-evaluations
|
|
39
|
+
* 5. Re-evaluates the query pipeline on each relevant change
|
|
40
|
+
* 6. Deduplicates consecutive identical result sets to avoid spurious emissions
|
|
41
|
+
* 7. Emits the new result set as a ReadonlyArray
|
|
42
|
+
*
|
|
43
|
+
* Resource management:
|
|
44
|
+
* - Uses Effect.acquireRelease to manage the PubSub subscription lifecycle
|
|
45
|
+
* - Subscription is acquired when the watch Effect runs and released when:
|
|
46
|
+
* - The enclosing Scope closes, OR
|
|
47
|
+
* - The stream is interrupted/completes (via Stream.ensuring)
|
|
48
|
+
* - This ensures no memory leaks from lingering subscriptions
|
|
49
|
+
*
|
|
50
|
+
* @param pubsub - The PubSub broadcasting ChangeEvents from mutations
|
|
51
|
+
* @param ref - The collection Ref containing entities keyed by ID
|
|
52
|
+
* @param collectionName - Name of the collection to watch (for filtering events)
|
|
53
|
+
* @param config - Optional query configuration (where, sort, select, limit, offset, debounceMs)
|
|
54
|
+
* @returns Scoped Effect producing a Stream of result arrays
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```ts
|
|
58
|
+
* const program = Effect.gen(function* () {
|
|
59
|
+
* const pubsub = yield* createChangePubSub()
|
|
60
|
+
* const ref = yield* createCollectionState<Book>([])
|
|
61
|
+
*
|
|
62
|
+
* const stream = yield* watch(pubsub, ref, "books", {
|
|
63
|
+
* where: { genre: "sci-fi" },
|
|
64
|
+
* sort: { year: "desc" },
|
|
65
|
+
* limit: 10,
|
|
66
|
+
* debounceMs: 50, // custom debounce interval
|
|
67
|
+
* })
|
|
68
|
+
*
|
|
69
|
+
* // Consume the stream
|
|
70
|
+
* yield* Stream.runForEach(stream, (results) =>
|
|
71
|
+
* Effect.log(`Got ${results.length} results`)
|
|
72
|
+
* )
|
|
73
|
+
* }).pipe(Effect.scoped)
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export declare const watch: <T extends HasId>(pubsub: PubSub.PubSub<ChangeEvent>, ref: Ref.Ref<ReadonlyMap<string, T>>, collectionName: string, config?: WatchQueryConfig) => Effect.Effect<Stream.Stream<ReadonlyArray<T>>, never, Scope.Scope>;
|
|
77
|
+
export {};
|
|
78
|
+
//# sourceMappingURL=watch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/reactive/watch.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAEN,MAAM,EAGN,MAAM,EACN,KAAK,GAAG,EACR,KAAK,EACL,MAAM,EACN,MAAM,QAAQ,CAAC;AAChB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,EAAE,KAAK,mBAAmB,EAAiB,MAAM,qBAAqB,CAAC;AAE9E;;;GAGG;AACH,MAAM,WAAW,gBAAiB,SAAQ,mBAAmB;IAC5D;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;GAEG;AACH,KAAK,KAAK,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAgCrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,eAAO,MAAM,KAAK,GAAI,CAAC,SAAS,KAAK,EACpC,QAAQ,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAClC,KAAK,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EACpC,gBAAgB,MAAM,EACtB,SAAQ,gBAAqB,KAC3B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAmFjE,CAAC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core watch() implementation for reactive queries.
|
|
3
|
+
*
|
|
4
|
+
* Creates a Stream that emits result sets whenever the underlying collection data changes.
|
|
5
|
+
* Subscribes to the PubSub for change notifications, filters events by collection name,
|
|
6
|
+
* re-evaluates the query pipeline on each change, deduplicates identical consecutive results,
|
|
7
|
+
* and emits the new result set.
|
|
8
|
+
*/
|
|
9
|
+
import { Duration, Effect, ExecutionStrategy, Exit, PubSub, Scope, Stream, } from "effect";
|
|
10
|
+
import { evaluateQuery } from "./evaluate-query.js";
|
|
11
|
+
/**
|
|
12
|
+
* Compares two result arrays for structural equality.
|
|
13
|
+
*
|
|
14
|
+
* Uses JSON serialization for deep comparison. This is simple and correct for
|
|
15
|
+
* comparing arrays of plain objects (which is what query results are).
|
|
16
|
+
*
|
|
17
|
+
* @param a - First result array
|
|
18
|
+
* @param b - Second result array
|
|
19
|
+
* @returns true if the arrays are structurally equal
|
|
20
|
+
*/
|
|
21
|
+
const resultsAreEqual = (a, b) => {
|
|
22
|
+
// Fast path: same reference
|
|
23
|
+
if (a === b)
|
|
24
|
+
return true;
|
|
25
|
+
// Fast path: different lengths
|
|
26
|
+
if (a.length !== b.length)
|
|
27
|
+
return false;
|
|
28
|
+
// Compare by serialization for deep structural equality
|
|
29
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Default debounce interval in milliseconds.
|
|
33
|
+
* Fast enough for interactive use, long enough to batch typical burst patterns.
|
|
34
|
+
*/
|
|
35
|
+
const DEFAULT_DEBOUNCE_MS = 10;
|
|
36
|
+
/**
|
|
37
|
+
* Creates a reactive watch stream that emits query results whenever the collection changes.
|
|
38
|
+
*
|
|
39
|
+
* The stream:
|
|
40
|
+
* 1. Emits the current result set immediately upon subscription
|
|
41
|
+
* 2. Subscribes to the PubSub for change notifications (scoped - auto-cleanup)
|
|
42
|
+
* 3. Filters events to only those matching the specified collection
|
|
43
|
+
* 4. Debounces change events to coalesce rapid mutations into single re-evaluations
|
|
44
|
+
* 5. Re-evaluates the query pipeline on each relevant change
|
|
45
|
+
* 6. Deduplicates consecutive identical result sets to avoid spurious emissions
|
|
46
|
+
* 7. Emits the new result set as a ReadonlyArray
|
|
47
|
+
*
|
|
48
|
+
* Resource management:
|
|
49
|
+
* - Uses Effect.acquireRelease to manage the PubSub subscription lifecycle
|
|
50
|
+
* - Subscription is acquired when the watch Effect runs and released when:
|
|
51
|
+
* - The enclosing Scope closes, OR
|
|
52
|
+
* - The stream is interrupted/completes (via Stream.ensuring)
|
|
53
|
+
* - This ensures no memory leaks from lingering subscriptions
|
|
54
|
+
*
|
|
55
|
+
* @param pubsub - The PubSub broadcasting ChangeEvents from mutations
|
|
56
|
+
* @param ref - The collection Ref containing entities keyed by ID
|
|
57
|
+
* @param collectionName - Name of the collection to watch (for filtering events)
|
|
58
|
+
* @param config - Optional query configuration (where, sort, select, limit, offset, debounceMs)
|
|
59
|
+
* @returns Scoped Effect producing a Stream of result arrays
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* const program = Effect.gen(function* () {
|
|
64
|
+
* const pubsub = yield* createChangePubSub()
|
|
65
|
+
* const ref = yield* createCollectionState<Book>([])
|
|
66
|
+
*
|
|
67
|
+
* const stream = yield* watch(pubsub, ref, "books", {
|
|
68
|
+
* where: { genre: "sci-fi" },
|
|
69
|
+
* sort: { year: "desc" },
|
|
70
|
+
* limit: 10,
|
|
71
|
+
* debounceMs: 50, // custom debounce interval
|
|
72
|
+
* })
|
|
73
|
+
*
|
|
74
|
+
* // Consume the stream
|
|
75
|
+
* yield* Stream.runForEach(stream, (results) =>
|
|
76
|
+
* Effect.log(`Got ${results.length} results`)
|
|
77
|
+
* )
|
|
78
|
+
* }).pipe(Effect.scoped)
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export const watch = (pubsub, ref, collectionName, config = {}) => Effect.gen(function* () {
|
|
82
|
+
// Get the current scope so we can fork a child scope for this subscription.
|
|
83
|
+
// The child scope allows us to clean up the subscription independently of
|
|
84
|
+
// the parent scope - either when the stream ends OR when the parent closes.
|
|
85
|
+
const parentScope = yield* Scope.Scope;
|
|
86
|
+
// Fork a child scope that will manage the subscription lifetime.
|
|
87
|
+
// When this child scope closes, the subscription will be cleaned up.
|
|
88
|
+
const subscriptionScope = yield* Scope.fork(parentScope, ExecutionStrategy.sequential);
|
|
89
|
+
// Use Effect.acquireRelease to manage the subscription:
|
|
90
|
+
// - Acquire: Subscribe to the PubSub (returns a Dequeue of ChangeEvents)
|
|
91
|
+
// - Release: Close the subscription scope (which triggers subscription cleanup)
|
|
92
|
+
//
|
|
93
|
+
// This explicit acquireRelease pattern makes the resource management visible
|
|
94
|
+
// and ensures proper cleanup when the stream is interrupted or completes.
|
|
95
|
+
const subscription = yield* Effect.acquireRelease(
|
|
96
|
+
// Acquire: Subscribe to the PubSub within the child scope
|
|
97
|
+
// PubSub.subscribe returns Effect<Dequeue, never, Scope.Scope>
|
|
98
|
+
// We provide the subscription scope so cleanup is tied to it
|
|
99
|
+
PubSub.subscribe(pubsub).pipe(Effect.provideService(Scope.Scope, subscriptionScope)),
|
|
100
|
+
// Release: Close the child scope to trigger subscription cleanup
|
|
101
|
+
// This runs when the enclosing scope closes
|
|
102
|
+
() => Scope.close(subscriptionScope, Exit.void));
|
|
103
|
+
// Create a stream from the subscription queue
|
|
104
|
+
const changeStream = Stream.fromQueue(subscription);
|
|
105
|
+
// Filter to only events for this collection
|
|
106
|
+
const filteredStream = Stream.filter(changeStream, (event) => event.collection === collectionName);
|
|
107
|
+
// Apply debouncing to coalesce rapid mutations into a single re-evaluation.
|
|
108
|
+
// This prevents re-evaluating the query on every single mutation when they
|
|
109
|
+
// arrive in bursts (e.g., createMany inserting 100 entities).
|
|
110
|
+
const debounceMs = config.debounceMs ?? DEFAULT_DEBOUNCE_MS;
|
|
111
|
+
const debouncedStream = Stream.debounce(filteredStream, Duration.millis(debounceMs));
|
|
112
|
+
// Map each (debounced) change event to a re-evaluation of the query.
|
|
113
|
+
// This transforms Stream<ChangeEvent> into Stream<ReadonlyArray<T>>
|
|
114
|
+
const changeResultStream = Stream.mapEffect(debouncedStream, () => evaluateQuery(ref, config));
|
|
115
|
+
// Create the initial emission stream: emit current result set immediately
|
|
116
|
+
const initialStream = Stream.fromEffect(evaluateQuery(ref, config));
|
|
117
|
+
// Concatenate initial emission with the change-driven stream
|
|
118
|
+
// This ensures subscribers receive the current state immediately,
|
|
119
|
+
// then receive updates as changes occur
|
|
120
|
+
const combinedStream = Stream.concat(initialStream, changeResultStream);
|
|
121
|
+
// Deduplicate consecutive identical result sets to avoid spurious emissions.
|
|
122
|
+
// This prevents re-emitting the same result set when a change event occurs
|
|
123
|
+
// but doesn't actually affect the query results (e.g., inserting an entity
|
|
124
|
+
// that doesn't match the where clause).
|
|
125
|
+
const deduplicatedStream = Stream.changesWith(combinedStream, resultsAreEqual);
|
|
126
|
+
// Ensure the subscription is cleaned up when the stream ends.
|
|
127
|
+
// This handles the case where the stream is interrupted or completed
|
|
128
|
+
// before the parent scope closes (e.g., Stream.take(n) stopping early).
|
|
129
|
+
// Closing the subscription scope triggers the acquireRelease cleanup.
|
|
130
|
+
const resultStream = Stream.ensuring(deduplicatedStream, Scope.close(subscriptionScope, Exit.void));
|
|
131
|
+
return resultStream;
|
|
132
|
+
});
|
|
133
|
+
//# sourceMappingURL=watch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/reactive/watch.ts"],"names":[],"mappings":"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"}
|