1import * as NodeFileSystem from "@effect/platform-node/NodeFileSystem"
2import * as NodePath from "@effect/platform-node/NodePath"
3import { assert, describe, it } from "@effect/vitest"
4import * as Effect from "effect/Effect"
5import * as FileSystem from "effect/FileSystem"
6import * as Layer from "effect/Layer"
7import * as KeyValueStore from "effect/persistence/KeyValueStore"
8
9const platformLayer = Layer.merge(NodeFileSystem.layer, NodePath.layer)
10
11describe("KeyValueStore / layerFileSystem", () => {
12 it.effect("rejects invalid keys without modifying the file system", () =>
13 Effect.gen(function*() {
14 const fs = yield* FileSystem.FileSystem
15 const root = yield* fs.makeTempDirectoryScoped()
16 const directory = `${root}/store`
17 const sibling = `${root}/sibling.txt`
18 yield* fs.makeDirectory(directory)
19 yield* fs.writeFileString(sibling, "sibling")
20
21 yield* Effect.gen(function*() {
22 const store = yield* KeyValueStore.KeyValueStore
23
24 for (const key of ["", ".", ".."]) {
25 const operations = [
26 ["get", Effect.asVoid(store.get(key))],
27 ["getUint8Array", Effect.asVoid(store.getUint8Array(key))],
28 ["set", Effect.asVoid(store.set(key, "value"))],
29 ["remove", Effect.asVoid(store.remove(key))],
30 ["has", Effect.asVoid(store.has(key))]
31 ] as const
32
33 for (const [method, operation] of operations) {
34 const error = yield* Effect.flip(operation)
35 assert.instanceOf(error, KeyValueStore.KeyValueStoreError)
36 assert.strictEqual(error.method, method)
37 assert.strictEqual(error.key, key)
38 }
39 }
40 }).pipe(
41 Effect.provide(KeyValueStore.layerFileSystem(directory).pipe(Layer.provide(platformLayer)))
42 )
43
44 assert.isTrue(yield* fs.exists(directory))
45 assert.deepStrictEqual(yield* fs.readDirectory(directory), [])
46 assert.strictEqual(yield* fs.readFileString(sibling), "sibling")
47 }).pipe(
48 Effect.provide(NodeFileSystem.layer)
49 ))
50})