storage.ts 1.3 KB

12345678910111213141516171819202122232425262728293031323334
  1. import { Option } from "effect"
  2. import * as fs from "node:fs"
  3. import * as path from "node:path"
  4. import { encodeCassette, decodeCassette, type Cassette, type CassetteMetadata, type Interaction } from "./schema"
  5. export const DEFAULT_RECORDINGS_DIR = path.resolve(process.cwd(), "test", "fixtures", "recordings")
  6. export const cassettePath = (name: string, directory = DEFAULT_RECORDINGS_DIR) => path.join(directory, `${name}.json`)
  7. export const metadataFor = (name: string, metadata: CassetteMetadata | undefined): CassetteMetadata => ({
  8. name,
  9. recordedAt: new Date().toISOString(),
  10. ...(metadata ?? {}),
  11. })
  12. export const cassetteFor = (
  13. name: string,
  14. interactions: ReadonlyArray<Interaction>,
  15. metadata: CassetteMetadata | undefined,
  16. ): Cassette => ({
  17. version: 1,
  18. metadata: metadataFor(name, metadata),
  19. interactions,
  20. })
  21. export const formatCassette = (cassette: Cassette) => `${JSON.stringify(encodeCassette(cassette), null, 2)}\n`
  22. export const parseCassette = (raw: string) => decodeCassette(JSON.parse(raw))
  23. export const hasCassetteSync = (name: string, options: { readonly directory?: string } = {}) => {
  24. const file = cassettePath(name, options.directory)
  25. if (!fs.existsSync(file)) return false
  26. return Option.isSome(Option.liftThrowable(parseCassette)(fs.readFileSync(file, "utf8")))
  27. }