@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,551 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Effect-based persistence functions for loading and saving collection data.
|
|
3
|
+
*
|
|
4
|
+
* Uses StorageAdapter and SerializerRegistry services for I/O and format handling.
|
|
5
|
+
* Data is decoded/encoded through Effect Schema on load/save to ensure type safety.
|
|
6
|
+
* Includes DebouncedWriter for coalescing rapid mutations into single file writes.
|
|
7
|
+
*/
|
|
8
|
+
import { Effect, Fiber, PubSub, Queue, Ref, Schema } from "effect";
|
|
9
|
+
import { ValidationError } from "../errors/crud-errors.js";
|
|
10
|
+
import { MigrationError } from "../errors/migration-errors.js";
|
|
11
|
+
import { SerializationError, StorageError, } from "../errors/storage-errors.js";
|
|
12
|
+
import { runMigrations } from "../migrations/migration-runner.js";
|
|
13
|
+
import { reloadEvent } from "../reactive/change-event.js";
|
|
14
|
+
import { SerializerRegistry } from "../serializers/serializer-service.js";
|
|
15
|
+
import { getFileExtension } from "../utils/path.js";
|
|
16
|
+
import { StorageAdapter } from "./storage-service.js";
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Helpers
|
|
19
|
+
// ============================================================================
|
|
20
|
+
/**
|
|
21
|
+
* Extract the file extension from a path, failing with StorageError if none found.
|
|
22
|
+
*/
|
|
23
|
+
const resolveExtension = (filePath) => {
|
|
24
|
+
const ext = getFileExtension(filePath);
|
|
25
|
+
if (ext === "") {
|
|
26
|
+
return Effect.fail(new StorageError({
|
|
27
|
+
path: filePath,
|
|
28
|
+
operation: "read",
|
|
29
|
+
message: `Cannot determine file format: no extension in '${filePath}'`,
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
return Effect.succeed(ext);
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Type guard: is the value a plain Record<string, unknown>?
|
|
36
|
+
*/
|
|
37
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
38
|
+
/**
|
|
39
|
+
* Load collection data from a file, decode each entity through the given Schema.
|
|
40
|
+
*
|
|
41
|
+
* Flow:
|
|
42
|
+
* 1. Check file existence via StorageAdapter
|
|
43
|
+
* 2. Read raw content
|
|
44
|
+
* 3. Deserialize via SerializerRegistry (format determined by file extension)
|
|
45
|
+
* 4. Validate the top-level structure is a Record<string, object>
|
|
46
|
+
* 5. Extract `_version` (default 0 if absent) and remove from entity map
|
|
47
|
+
* 6. Decode each entity value through the Schema
|
|
48
|
+
* 7. Return a ReadonlyMap<string, A> keyed by entity ID
|
|
49
|
+
*
|
|
50
|
+
* If the file does not exist, returns an empty ReadonlyMap.
|
|
51
|
+
*
|
|
52
|
+
* When `options.version` is provided:
|
|
53
|
+
* - Extracts `_version` from the file (defaults to 0 if absent)
|
|
54
|
+
* - Compares file version to config version
|
|
55
|
+
* - If file version < config version: runs migrations (task 5.2)
|
|
56
|
+
* - If file version > config version: fails with MigrationError
|
|
57
|
+
* - If file version === config version: proceeds normally
|
|
58
|
+
*/
|
|
59
|
+
export const loadData = (filePath, schema, options) => Effect.gen(function* () {
|
|
60
|
+
const storage = yield* StorageAdapter;
|
|
61
|
+
const serializer = yield* SerializerRegistry;
|
|
62
|
+
const ext = yield* resolveExtension(filePath);
|
|
63
|
+
// If file doesn't exist, return empty map
|
|
64
|
+
const exists = yield* storage.exists(filePath);
|
|
65
|
+
if (!exists) {
|
|
66
|
+
return new Map();
|
|
67
|
+
}
|
|
68
|
+
// Read and deserialize
|
|
69
|
+
const raw = yield* storage.read(filePath);
|
|
70
|
+
const parsed = yield* serializer.deserialize(raw, ext);
|
|
71
|
+
// The on-disk format depends on the file extension:
|
|
72
|
+
// - JSONL/NDJSON: array of entity objects (one entity per line)
|
|
73
|
+
// - All other formats: Record<string, object> keyed by entity ID
|
|
74
|
+
const isJsonl = ext === "jsonl" || ext === "ndjson";
|
|
75
|
+
const entityMap = {};
|
|
76
|
+
let fileVersion = 0;
|
|
77
|
+
if (isJsonl && Array.isArray(parsed)) {
|
|
78
|
+
// JSONL format: array of entity objects → convert to Record keyed by id
|
|
79
|
+
for (const item of parsed) {
|
|
80
|
+
if (isRecord(item) && typeof item.id === "string") {
|
|
81
|
+
entityMap[item.id] = item;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else if (isRecord(parsed)) {
|
|
86
|
+
// Standard format: Record keyed by entity ID
|
|
87
|
+
fileVersion = typeof parsed._version === "number" ? parsed._version : 0;
|
|
88
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
89
|
+
if (key !== "_version") {
|
|
90
|
+
entityMap[key] = value;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
return yield* Effect.fail(new SerializationError({
|
|
96
|
+
format: ext,
|
|
97
|
+
message: `Invalid data format in '${filePath}': expected object, got ${typeof parsed}`,
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
// Determine the data to decode (may be migrated)
|
|
101
|
+
let dataToLoad = entityMap;
|
|
102
|
+
let needsWriteBack = false;
|
|
103
|
+
let targetVersion;
|
|
104
|
+
// Track if migrations were run (for post-migration validation error type)
|
|
105
|
+
let migrationsRan = false;
|
|
106
|
+
const fromVersionForError = fileVersion;
|
|
107
|
+
let collectionNameForError = "unknown";
|
|
108
|
+
// If version checking is enabled, validate version compatibility
|
|
109
|
+
if (options?.version !== undefined) {
|
|
110
|
+
const configVersion = options.version;
|
|
111
|
+
const collectionName = options.collectionName ?? "unknown";
|
|
112
|
+
collectionNameForError = collectionName;
|
|
113
|
+
// File version ahead of config version is an error
|
|
114
|
+
if (fileVersion > configVersion) {
|
|
115
|
+
return yield* Effect.fail(new MigrationError({
|
|
116
|
+
collection: collectionName,
|
|
117
|
+
fromVersion: configVersion,
|
|
118
|
+
toVersion: fileVersion,
|
|
119
|
+
step: -1,
|
|
120
|
+
reason: "version-ahead",
|
|
121
|
+
message: `File version ${fileVersion} is ahead of config version ${configVersion}. Cannot load data from a future version.`,
|
|
122
|
+
}));
|
|
123
|
+
}
|
|
124
|
+
// If file version < config version and migrations are provided, run migrations
|
|
125
|
+
if (fileVersion < configVersion &&
|
|
126
|
+
options.migrations &&
|
|
127
|
+
options.migrations.length > 0) {
|
|
128
|
+
dataToLoad = yield* runMigrations(entityMap, fileVersion, configVersion, options.migrations, collectionName);
|
|
129
|
+
needsWriteBack = true;
|
|
130
|
+
targetVersion = configVersion;
|
|
131
|
+
migrationsRan = true;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
// Decode each entity through the schema
|
|
135
|
+
const decode = Schema.decodeUnknown(schema);
|
|
136
|
+
const entries = [];
|
|
137
|
+
for (const [id, value] of Object.entries(dataToLoad)) {
|
|
138
|
+
const decoded = yield* decode(value).pipe(Effect.mapError((parseError) =>
|
|
139
|
+
// If migrations were run, produce MigrationError with step: -1
|
|
140
|
+
// Otherwise, produce ValidationError for normal schema mismatch
|
|
141
|
+
migrationsRan
|
|
142
|
+
? new MigrationError({
|
|
143
|
+
collection: collectionNameForError,
|
|
144
|
+
fromVersion: fromVersionForError,
|
|
145
|
+
toVersion: targetVersion ?? 0,
|
|
146
|
+
step: -1,
|
|
147
|
+
reason: "post-migration-validation-failed",
|
|
148
|
+
message: `Post-migration validation failed for entity '${id}': ${parseError.message}`,
|
|
149
|
+
})
|
|
150
|
+
: new ValidationError({
|
|
151
|
+
message: `Failed to decode entity '${id}' in '${filePath}': ${parseError.message}`,
|
|
152
|
+
issues: [
|
|
153
|
+
{
|
|
154
|
+
field: id,
|
|
155
|
+
message: parseError.message,
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
})));
|
|
159
|
+
entries.push([id, decoded]);
|
|
160
|
+
}
|
|
161
|
+
const result = new Map(entries);
|
|
162
|
+
// If migrations were run, write the migrated data back to disk with new version
|
|
163
|
+
if (needsWriteBack && targetVersion !== undefined) {
|
|
164
|
+
yield* saveData(filePath, schema, result, { version: targetVersion });
|
|
165
|
+
}
|
|
166
|
+
return result;
|
|
167
|
+
});
|
|
168
|
+
/**
|
|
169
|
+
* Save collection data to a file, encoding each entity through the given Schema.
|
|
170
|
+
*
|
|
171
|
+
* Flow:
|
|
172
|
+
* 1. Encode each entity through the Schema (Type → Encoded)
|
|
173
|
+
* 2. Build a Record<string, I> keyed by entity ID
|
|
174
|
+
* 3. Optionally inject `_version` at the top level if version is provided
|
|
175
|
+
* 4. Serialize via SerializerRegistry
|
|
176
|
+
* 5. Ensure parent directory exists
|
|
177
|
+
* 6. Write via StorageAdapter
|
|
178
|
+
*/
|
|
179
|
+
export const saveData = (filePath, schema, data, options) => Effect.gen(function* () {
|
|
180
|
+
const storage = yield* StorageAdapter;
|
|
181
|
+
const serializer = yield* SerializerRegistry;
|
|
182
|
+
const ext = yield* resolveExtension(filePath);
|
|
183
|
+
// Encode each entity through the schema
|
|
184
|
+
const encode = Schema.encode(schema);
|
|
185
|
+
const isJsonl = ext === "jsonl" || ext === "ndjson";
|
|
186
|
+
if (isJsonl) {
|
|
187
|
+
// JSONL format: encode as array of entities (one JSON line per entity)
|
|
188
|
+
const entities = [];
|
|
189
|
+
for (const [id, entity] of data) {
|
|
190
|
+
const encoded = yield* encode(entity).pipe(Effect.mapError((parseError) => new ValidationError({
|
|
191
|
+
message: `Failed to encode entity '${id}' for '${filePath}': ${parseError.message}`,
|
|
192
|
+
issues: [
|
|
193
|
+
{
|
|
194
|
+
field: id,
|
|
195
|
+
message: parseError.message,
|
|
196
|
+
},
|
|
197
|
+
],
|
|
198
|
+
})));
|
|
199
|
+
entities.push(encoded);
|
|
200
|
+
}
|
|
201
|
+
const content = yield* serializer.serialize(entities, ext);
|
|
202
|
+
yield* storage.ensureDir(filePath);
|
|
203
|
+
yield* storage.write(filePath, content);
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
// Standard format: encode as Record keyed by entity ID
|
|
207
|
+
const entityMap = {};
|
|
208
|
+
for (const [id, entity] of data) {
|
|
209
|
+
const encoded = yield* encode(entity).pipe(Effect.mapError((parseError) => new ValidationError({
|
|
210
|
+
message: `Failed to encode entity '${id}' for '${filePath}': ${parseError.message}`,
|
|
211
|
+
issues: [
|
|
212
|
+
{
|
|
213
|
+
field: id,
|
|
214
|
+
message: parseError.message,
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
})));
|
|
218
|
+
entityMap[id] = encoded;
|
|
219
|
+
}
|
|
220
|
+
// Build output object, injecting _version first if provided for readability
|
|
221
|
+
const output = options?.version !== undefined
|
|
222
|
+
? { _version: options.version, ...entityMap }
|
|
223
|
+
: entityMap;
|
|
224
|
+
// Serialize and write
|
|
225
|
+
const content = yield* serializer.serialize(output, ext);
|
|
226
|
+
yield* storage.ensureDir(filePath);
|
|
227
|
+
yield* storage.write(filePath, content);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
/**
|
|
231
|
+
* Load multiple collections from a single file.
|
|
232
|
+
*
|
|
233
|
+
* The file is expected to contain a top-level object where keys are collection names
|
|
234
|
+
* and values are objects keyed by entity ID. Each collection is decoded independently
|
|
235
|
+
* using its own schema.
|
|
236
|
+
*
|
|
237
|
+
* When collections have `version` and `migrations` specified, per-collection migration
|
|
238
|
+
* is applied:
|
|
239
|
+
* - Each collection's `_version` is extracted from its section (default 0 if absent)
|
|
240
|
+
* - If file version < config version: migrations run for that collection
|
|
241
|
+
* - If file version > config version: fails with MigrationError
|
|
242
|
+
* - After any migrations, the entire file is rewritten with all collections at their current versions
|
|
243
|
+
*
|
|
244
|
+
* Returns a Record mapping collection name to ReadonlyMap<string, unknown>.
|
|
245
|
+
*/
|
|
246
|
+
export const loadCollectionsFromFile = (filePath, collections) => Effect.gen(function* () {
|
|
247
|
+
const storage = yield* StorageAdapter;
|
|
248
|
+
const serializer = yield* SerializerRegistry;
|
|
249
|
+
const ext = yield* resolveExtension(filePath);
|
|
250
|
+
const exists = yield* storage.exists(filePath);
|
|
251
|
+
if (!exists) {
|
|
252
|
+
const result = {};
|
|
253
|
+
for (const col of collections) {
|
|
254
|
+
result[col.name] = new Map();
|
|
255
|
+
}
|
|
256
|
+
return result;
|
|
257
|
+
}
|
|
258
|
+
const raw = yield* storage.read(filePath);
|
|
259
|
+
const parsed = yield* serializer.deserialize(raw, ext);
|
|
260
|
+
if (!isRecord(parsed)) {
|
|
261
|
+
return yield* Effect.fail(new SerializationError({
|
|
262
|
+
format: ext,
|
|
263
|
+
message: `Invalid data format in '${filePath}': expected object, got ${typeof parsed}`,
|
|
264
|
+
}));
|
|
265
|
+
}
|
|
266
|
+
const result = {};
|
|
267
|
+
// Track which collections need write-back after migration
|
|
268
|
+
let needsWriteBack = false;
|
|
269
|
+
// Store migrated data for write-back (maps collection name to encoded entities + version)
|
|
270
|
+
const writeBackData = [];
|
|
271
|
+
for (const col of collections) {
|
|
272
|
+
const collectionData = parsed[col.name];
|
|
273
|
+
if (collectionData === undefined || !isRecord(collectionData)) {
|
|
274
|
+
result[col.name] = new Map();
|
|
275
|
+
// Build write-back entry, only adding version if defined
|
|
276
|
+
const emptyEntry = {
|
|
277
|
+
name: col.name,
|
|
278
|
+
schema: col.schema,
|
|
279
|
+
data: new Map(),
|
|
280
|
+
};
|
|
281
|
+
if (col.version !== undefined) {
|
|
282
|
+
writeBackData.push({ ...emptyEntry, version: col.version });
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
writeBackData.push(emptyEntry);
|
|
286
|
+
}
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
// Extract _version from collection data (default 0 if absent)
|
|
290
|
+
const fileVersion = typeof collectionData._version === "number"
|
|
291
|
+
? collectionData._version
|
|
292
|
+
: 0;
|
|
293
|
+
// Create entity map without _version
|
|
294
|
+
const entityMap = {};
|
|
295
|
+
for (const [key, value] of Object.entries(collectionData)) {
|
|
296
|
+
if (key !== "_version") {
|
|
297
|
+
entityMap[key] = value;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
// Determine the data to decode (may be migrated)
|
|
301
|
+
let dataToLoad = entityMap;
|
|
302
|
+
let collectionNeedsMigration = false;
|
|
303
|
+
// If version checking is enabled, validate version compatibility
|
|
304
|
+
if (col.version !== undefined) {
|
|
305
|
+
const configVersion = col.version;
|
|
306
|
+
// File version ahead of config version is an error
|
|
307
|
+
if (fileVersion > configVersion) {
|
|
308
|
+
return yield* Effect.fail(new MigrationError({
|
|
309
|
+
collection: col.name,
|
|
310
|
+
fromVersion: configVersion,
|
|
311
|
+
toVersion: fileVersion,
|
|
312
|
+
step: -1,
|
|
313
|
+
reason: "version-ahead",
|
|
314
|
+
message: `File version ${fileVersion} for collection "${col.name}" is ahead of config version ${configVersion}. Cannot load data from a future version.`,
|
|
315
|
+
}));
|
|
316
|
+
}
|
|
317
|
+
// If file version < config version and migrations are provided, run migrations
|
|
318
|
+
if (fileVersion < configVersion &&
|
|
319
|
+
col.migrations &&
|
|
320
|
+
col.migrations.length > 0) {
|
|
321
|
+
dataToLoad = yield* runMigrations(entityMap, fileVersion, configVersion, col.migrations, col.name);
|
|
322
|
+
collectionNeedsMigration = true;
|
|
323
|
+
needsWriteBack = true;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
// Decode each entity through the schema
|
|
327
|
+
const decode = Schema.decodeUnknown(col.schema);
|
|
328
|
+
const entries = [];
|
|
329
|
+
for (const [id, value] of Object.entries(dataToLoad)) {
|
|
330
|
+
const decoded = yield* decode(value).pipe(Effect.mapError((parseError) =>
|
|
331
|
+
// If migrations were run, produce MigrationError with step: -1
|
|
332
|
+
// Otherwise, produce ValidationError for normal schema mismatch
|
|
333
|
+
collectionNeedsMigration
|
|
334
|
+
? new MigrationError({
|
|
335
|
+
collection: col.name,
|
|
336
|
+
fromVersion: fileVersion,
|
|
337
|
+
toVersion: col.version ?? 0,
|
|
338
|
+
step: -1,
|
|
339
|
+
reason: "post-migration-validation-failed",
|
|
340
|
+
message: `Post-migration validation failed for entity '${id}': ${parseError.message}`,
|
|
341
|
+
})
|
|
342
|
+
: new ValidationError({
|
|
343
|
+
message: `Failed to decode entity '${id}' in collection '${col.name}' from '${filePath}': ${parseError.message}`,
|
|
344
|
+
issues: [
|
|
345
|
+
{
|
|
346
|
+
field: `${col.name}.${id}`,
|
|
347
|
+
message: parseError.message,
|
|
348
|
+
},
|
|
349
|
+
],
|
|
350
|
+
})));
|
|
351
|
+
entries.push([id, decoded]);
|
|
352
|
+
}
|
|
353
|
+
const collectionMap = new Map(entries);
|
|
354
|
+
result[col.name] = collectionMap;
|
|
355
|
+
// Track for write-back, only adding version if defined
|
|
356
|
+
const entry = {
|
|
357
|
+
name: col.name,
|
|
358
|
+
schema: col.schema,
|
|
359
|
+
data: collectionMap,
|
|
360
|
+
};
|
|
361
|
+
// Use the target version if versioned collection (whether migrated or not)
|
|
362
|
+
if (col.version !== undefined) {
|
|
363
|
+
writeBackData.push({ ...entry, version: col.version });
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
writeBackData.push(entry);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
// If any collection was migrated, write back the entire file
|
|
370
|
+
if (needsWriteBack) {
|
|
371
|
+
yield* saveCollectionsToFile(filePath, writeBackData);
|
|
372
|
+
}
|
|
373
|
+
return result;
|
|
374
|
+
});
|
|
375
|
+
/**
|
|
376
|
+
* Save multiple collections to a single file.
|
|
377
|
+
*
|
|
378
|
+
* Encodes each entity in each collection through its schema, then writes
|
|
379
|
+
* the combined data as { collectionName: { _version?, id: encodedEntity, ... }, ... }.
|
|
380
|
+
*
|
|
381
|
+
* If a collection has a `version` specified, `_version` is stamped first
|
|
382
|
+
* in that collection's object for readability.
|
|
383
|
+
*/
|
|
384
|
+
export function saveCollectionsToFile(filePath, collections) {
|
|
385
|
+
return Effect.gen(function* () {
|
|
386
|
+
const storage = yield* StorageAdapter;
|
|
387
|
+
const serializer = yield* SerializerRegistry;
|
|
388
|
+
const ext = yield* resolveExtension(filePath);
|
|
389
|
+
const fileObj = {};
|
|
390
|
+
for (const col of collections) {
|
|
391
|
+
const encode = Schema.encode(col.schema);
|
|
392
|
+
const entityMap = {};
|
|
393
|
+
for (const [id, entity] of col.data) {
|
|
394
|
+
const encoded = yield* encode(entity).pipe(Effect.mapError((parseError) => new ValidationError({
|
|
395
|
+
message: `Failed to encode entity '${id}' in collection '${col.name}' for '${filePath}': ${parseError.message}`,
|
|
396
|
+
issues: [
|
|
397
|
+
{
|
|
398
|
+
field: `${col.name}.${id}`,
|
|
399
|
+
message: parseError.message,
|
|
400
|
+
},
|
|
401
|
+
],
|
|
402
|
+
})));
|
|
403
|
+
entityMap[id] = encoded;
|
|
404
|
+
}
|
|
405
|
+
// Inject _version first if provided for readability
|
|
406
|
+
fileObj[col.name] =
|
|
407
|
+
col.version !== undefined
|
|
408
|
+
? { _version: col.version, ...entityMap }
|
|
409
|
+
: entityMap;
|
|
410
|
+
}
|
|
411
|
+
const content = yield* serializer.serialize(fileObj, ext);
|
|
412
|
+
yield* storage.ensureDir(filePath);
|
|
413
|
+
yield* storage.write(filePath, content);
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Create a DebouncedWriter that coalesces rapid writes into single file operations.
|
|
418
|
+
*
|
|
419
|
+
* Each call to `triggerSave(key, saveEffect)` cancels any pending write for
|
|
420
|
+
* that key and schedules a new one after `delayMs` milliseconds. If another
|
|
421
|
+
* `triggerSave` for the same key arrives before the delay elapses, the timer
|
|
422
|
+
* resets — only the last write within a burst actually hits the filesystem.
|
|
423
|
+
*
|
|
424
|
+
* @param delayMs - Debounce delay in milliseconds (default 100)
|
|
425
|
+
*/
|
|
426
|
+
export const createDebouncedWriter = (delayMs = 100) => Effect.gen(function* () {
|
|
427
|
+
const pending = yield* Ref.make(new Map());
|
|
428
|
+
const triggerSave = (key, save) => Effect.gen(function* () {
|
|
429
|
+
// Cancel existing pending write for this key if any
|
|
430
|
+
const current = yield* Ref.get(pending);
|
|
431
|
+
const existing = current.get(key);
|
|
432
|
+
if (existing !== undefined) {
|
|
433
|
+
yield* Fiber.interrupt(existing.fiber);
|
|
434
|
+
}
|
|
435
|
+
// Fork a fiber that sleeps then executes the save
|
|
436
|
+
const fiber = yield* Effect.fork(Effect.gen(function* () {
|
|
437
|
+
yield* Effect.sleep(delayMs);
|
|
438
|
+
yield* save;
|
|
439
|
+
// Remove from pending after successful write
|
|
440
|
+
yield* Ref.update(pending, (m) => {
|
|
441
|
+
const next = new Map(m);
|
|
442
|
+
next.delete(key);
|
|
443
|
+
return next;
|
|
444
|
+
});
|
|
445
|
+
}));
|
|
446
|
+
// Store the pending write
|
|
447
|
+
yield* Ref.update(pending, (m) => {
|
|
448
|
+
const next = new Map(m);
|
|
449
|
+
next.set(key, { fiber, save });
|
|
450
|
+
return next;
|
|
451
|
+
});
|
|
452
|
+
});
|
|
453
|
+
const flush = () => Effect.gen(function* () {
|
|
454
|
+
// Atomically take all pending writes and clear the map
|
|
455
|
+
const writes = yield* Ref.getAndSet(pending, new Map());
|
|
456
|
+
// Interrupt all pending fibers first
|
|
457
|
+
for (const [, entry] of writes) {
|
|
458
|
+
yield* Fiber.interrupt(entry.fiber);
|
|
459
|
+
}
|
|
460
|
+
// Execute all saves immediately
|
|
461
|
+
for (const [, entry] of writes) {
|
|
462
|
+
yield* entry.save;
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
const pendingCount = () => Ref.get(pending).pipe(Effect.map((m) => m.size));
|
|
466
|
+
return { triggerSave, flush, pendingCount };
|
|
467
|
+
});
|
|
468
|
+
/**
|
|
469
|
+
* Create a managed file watcher using Effect.acquireRelease.
|
|
470
|
+
*
|
|
471
|
+
* The watcher monitors a file for external changes. When a change is detected,
|
|
472
|
+
* it reloads the file through the Schema and updates the collection Ref.
|
|
473
|
+
*
|
|
474
|
+
* The watcher lifecycle is managed by Effect's Scope — it is automatically
|
|
475
|
+
* closed when the Scope finalizes (database shutdown, test cleanup, etc.).
|
|
476
|
+
*
|
|
477
|
+
* Reload is debounced to avoid redundant reloads when editors write
|
|
478
|
+
* multiple change events in quick succession.
|
|
479
|
+
*
|
|
480
|
+
* @param config - File watcher configuration
|
|
481
|
+
* @returns Effect that yields a FileWatcher handle (requires Scope)
|
|
482
|
+
*/
|
|
483
|
+
export const createFileWatcher = (config) => {
|
|
484
|
+
const debounceMs = config.debounceMs ?? 50;
|
|
485
|
+
return Effect.gen(function* () {
|
|
486
|
+
const storage = yield* StorageAdapter;
|
|
487
|
+
const active = yield* Ref.make(true);
|
|
488
|
+
// Queue bridges the sync onChange callback to the Effect world.
|
|
489
|
+
// The callback pushes a signal; a background fiber consumes it.
|
|
490
|
+
const changeQueue = yield* Queue.unbounded();
|
|
491
|
+
// Ref to hold the debounce timer fiber so it can be cancelled on new events
|
|
492
|
+
const pendingReload = yield* Ref.make(null);
|
|
493
|
+
// Background fiber: waits for change signals, debounces, then reloads.
|
|
494
|
+
const processorFiber = yield* Effect.fork(Effect.forever(Effect.gen(function* () {
|
|
495
|
+
// Block until a change signal arrives
|
|
496
|
+
yield* Queue.take(changeQueue);
|
|
497
|
+
// Drain any queued signals (batch rapid events)
|
|
498
|
+
yield* Queue.takeAll(changeQueue);
|
|
499
|
+
const isActive = yield* Ref.get(active);
|
|
500
|
+
if (!isActive)
|
|
501
|
+
return;
|
|
502
|
+
// Cancel any existing pending reload
|
|
503
|
+
const existing = yield* Ref.get(pendingReload);
|
|
504
|
+
if (existing !== null) {
|
|
505
|
+
yield* Fiber.interrupt(existing);
|
|
506
|
+
}
|
|
507
|
+
// Fork a debounced reload
|
|
508
|
+
const fiber = yield* Effect.fork(Effect.gen(function* () {
|
|
509
|
+
yield* Effect.sleep(debounceMs);
|
|
510
|
+
const newData = yield* loadData(config.filePath, config.schema);
|
|
511
|
+
yield* Ref.set(config.ref, newData);
|
|
512
|
+
// Publish reload event if PubSub is provided
|
|
513
|
+
if (config.changePubSub !== undefined &&
|
|
514
|
+
config.collectionName !== undefined) {
|
|
515
|
+
yield* PubSub.publish(config.changePubSub, reloadEvent(config.collectionName));
|
|
516
|
+
}
|
|
517
|
+
}));
|
|
518
|
+
yield* Ref.set(pendingReload, fiber);
|
|
519
|
+
})));
|
|
520
|
+
// Acquire the watcher via StorageAdapter.watch, release by calling the
|
|
521
|
+
// returned stop function. acquireRelease ties the lifetime to the Scope.
|
|
522
|
+
yield* Effect.acquireRelease(storage.watch(config.filePath, () => {
|
|
523
|
+
// Push a change signal into the queue (sync-safe)
|
|
524
|
+
Queue.unsafeOffer(changeQueue, undefined);
|
|
525
|
+
}), (stopWatching) => Effect.gen(function* () {
|
|
526
|
+
yield* Ref.set(active, false);
|
|
527
|
+
// Stop the processor fiber
|
|
528
|
+
yield* Fiber.interrupt(processorFiber);
|
|
529
|
+
// Cancel any pending reload
|
|
530
|
+
const pending = yield* Ref.get(pendingReload);
|
|
531
|
+
if (pending !== null) {
|
|
532
|
+
yield* Fiber.interrupt(pending);
|
|
533
|
+
}
|
|
534
|
+
stopWatching();
|
|
535
|
+
}));
|
|
536
|
+
return {
|
|
537
|
+
isActive: () => Ref.get(active),
|
|
538
|
+
};
|
|
539
|
+
});
|
|
540
|
+
};
|
|
541
|
+
/**
|
|
542
|
+
* Create managed file watchers for multiple files at once.
|
|
543
|
+
*
|
|
544
|
+
* Convenience wrapper that creates a watcher for each config entry.
|
|
545
|
+
* All watchers share the enclosing Scope and are cleaned up together.
|
|
546
|
+
*
|
|
547
|
+
* @param configs - Array of file watcher configurations
|
|
548
|
+
* @returns Effect yielding an array of FileWatcher handles
|
|
549
|
+
*/
|
|
550
|
+
export const createFileWatchers = (configs) => Effect.all(configs.map((cfg) => createFileWatcher(cfg)), { concurrency: "unbounded" });
|
|
551
|
+
//# sourceMappingURL=persistence-effect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence-effect.js","sourceRoot":"","sources":["../../src/storage/persistence-effect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Context, type Effect } from "effect";
|
|
2
|
+
import type { StorageError, UnsupportedFormatError } from "../errors/storage-errors.js";
|
|
3
|
+
/**
|
|
4
|
+
* Error types that can occur during storage read/write operations.
|
|
5
|
+
* Includes StorageError for I/O failures and UnsupportedFormatError
|
|
6
|
+
* for format validation (e.g., when allowedFormats config is set).
|
|
7
|
+
*/
|
|
8
|
+
export type StorageReadWriteError = StorageError | UnsupportedFormatError;
|
|
9
|
+
export interface StorageAdapterShape {
|
|
10
|
+
readonly read: (path: string) => Effect.Effect<string, StorageReadWriteError>;
|
|
11
|
+
readonly write: (path: string, data: string) => Effect.Effect<void, StorageReadWriteError>;
|
|
12
|
+
readonly append: (path: string, data: string) => Effect.Effect<void, StorageReadWriteError>;
|
|
13
|
+
readonly exists: (path: string) => Effect.Effect<boolean, StorageError>;
|
|
14
|
+
readonly remove: (path: string) => Effect.Effect<void, StorageError>;
|
|
15
|
+
readonly ensureDir: (path: string) => Effect.Effect<void, StorageError>;
|
|
16
|
+
readonly watch: (path: string, onChange: () => void) => Effect.Effect</** stop watching */ () => void, StorageError>;
|
|
17
|
+
}
|
|
18
|
+
declare const StorageAdapter_base: Context.TagClass<StorageAdapter, "StorageAdapter", StorageAdapterShape>;
|
|
19
|
+
export declare class StorageAdapter extends StorageAdapter_base {
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=storage-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-service.d.ts","sourceRoot":"","sources":["../../src/storage/storage-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,KAAK,EACX,YAAY,EACZ,sBAAsB,EACtB,MAAM,6BAA6B,CAAC;AAMrC;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAAG,YAAY,GAAG,sBAAsB,CAAC;AAE1E,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC;IAC9E,QAAQ,CAAC,KAAK,EAAE,CACf,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,KACR,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,CAChB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,KACR,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;IACxE,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACrE,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;IACxE,QAAQ,CAAC,KAAK,EAAE,CACf,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,IAAI,KAChB,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,MAAM,IAAI,EAAE,YAAY,CAAC,CAAC;CAClE;;AAED,qBAAa,cAAe,SAAQ,mBAGjC;CAAG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-service.js","sourceRoot":"","sources":["../../src/storage/storage-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAe,MAAM,QAAQ,CAAC;AAoC9C,MAAM,OAAO,cAAe,SAAQ,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAG9D;CAAG"}
|