support.ts 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import { NodeFileSystem } from "@effect/platform-node-shared"
  2. import { Cause, Effect, Exit } from "effect"
  3. import { HttpBody, HttpClient, HttpClientRequest } from "effect/unstable/http"
  4. import { mkdtempSync, readFileSync, rmSync } from "node:fs"
  5. import { tmpdir } from "node:os"
  6. import { join } from "node:path"
  7. import { decodeCassette, type Interaction } from "../src/cassette/model"
  8. import { Service, fileSystem } from "../src/cassette/store"
  9. export const tempDirectory = (prefix: string) => {
  10. const directory = mkdtempSync(join(tmpdir(), prefix))
  11. return {
  12. path: directory,
  13. [Symbol.dispose]() {
  14. rmSync(directory, { recursive: true, force: true })
  15. },
  16. }
  17. }
  18. export const post = (url: string, body: object) =>
  19. Effect.gen(function* () {
  20. const http = yield* HttpClient.HttpClient
  21. const response = yield* http.execute(
  22. HttpClientRequest.post(url, {
  23. headers: { "content-type": "application/json" },
  24. body: HttpBody.text(JSON.stringify(body), "application/json"),
  25. }),
  26. )
  27. return yield* response.text
  28. })
  29. export const readCassette = (file: string) => decodeCassette(JSON.parse(readFileSync(file, "utf8")))
  30. export const runFileCassette = <A, E>(directory: string, effect: Effect.Effect<A, E, Service>) =>
  31. Effect.runPromise(effect.pipe(Effect.provide(fileSystem({ directory })), Effect.provide(NodeFileSystem.layer)))
  32. export const seedCassetteDirectory = (directory: string, name: string, interactions: ReadonlyArray<Interaction>) =>
  33. runFileCassette(
  34. directory,
  35. Effect.gen(function* () {
  36. const cassette = yield* Service
  37. yield* Effect.forEach(interactions, (interaction) => cassette.append(name, interaction))
  38. }),
  39. )
  40. export const withEnvironment = async <A>(name: string, value: string | undefined, run: () => Promise<A>) => {
  41. const previous = process.env[name]
  42. if (value === undefined) delete process.env[name]
  43. else process.env[name] = value
  44. try {
  45. return await run()
  46. } finally {
  47. if (previous === undefined) delete process.env[name]
  48. else process.env[name] = previous
  49. }
  50. }
  51. export const failureText = (exit: Exit.Exit<unknown, unknown>) => {
  52. if (Exit.isSuccess(exit)) return ""
  53. return Cause.prettyErrors(exit.cause).join("\n")
  54. }