schema.ts 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { Schema } from "effect"
  2. import type {
  3. CassetteMetadata,
  4. HttpInteraction,
  5. RequestSnapshot,
  6. ResponseSnapshot,
  7. WebSocketEvent,
  8. WebSocketInteraction,
  9. } from "./types.js"
  10. export type {
  11. CassetteMetadata,
  12. HttpInteraction,
  13. RequestSnapshot,
  14. ResponseSnapshot,
  15. WebSocketEvent,
  16. WebSocketInteraction,
  17. } from "./types.js"
  18. export const RequestSnapshotSchema = Schema.Struct({
  19. method: Schema.String,
  20. url: Schema.String,
  21. headers: Schema.Record(Schema.String, Schema.String),
  22. body: Schema.String,
  23. })
  24. export const ResponseSnapshotSchema = Schema.Struct({
  25. status: Schema.Number,
  26. headers: Schema.Record(Schema.String, Schema.String),
  27. body: Schema.String,
  28. bodyEncoding: Schema.optional(Schema.Literals(["text", "base64"])),
  29. })
  30. export const CassetteMetadataSchema = Schema.Record(Schema.String, Schema.Unknown)
  31. export const HttpInteractionSchema = Schema.Struct({
  32. transport: Schema.tag("http"),
  33. request: RequestSnapshotSchema,
  34. response: ResponseSnapshotSchema,
  35. })
  36. export const WebSocketEventSchema = Schema.Union([
  37. Schema.Struct({
  38. direction: Schema.Literals(["client", "server"]),
  39. kind: Schema.tag("text"),
  40. body: Schema.String,
  41. }),
  42. Schema.Struct({
  43. direction: Schema.Literals(["client", "server"]),
  44. kind: Schema.tag("binary"),
  45. body: Schema.String,
  46. bodyEncoding: Schema.Literal("base64"),
  47. }),
  48. ])
  49. export const WebSocketInteractionSchema = Schema.Struct({
  50. transport: Schema.tag("websocket"),
  51. open: Schema.Struct({
  52. url: Schema.String,
  53. headers: Schema.Record(Schema.String, Schema.String),
  54. }),
  55. events: Schema.Array(WebSocketEventSchema),
  56. })
  57. export const InteractionSchema = Schema.Union([HttpInteractionSchema, WebSocketInteractionSchema]).pipe(
  58. Schema.toTaggedUnion("transport"),
  59. )
  60. export type Interaction = Schema.Schema.Type<typeof InteractionSchema>
  61. export const isHttpInteraction = InteractionSchema.guards.http
  62. export const isWebSocketInteraction = InteractionSchema.guards.websocket
  63. export const httpInteractions = (interactions: ReadonlyArray<Interaction>) => interactions.filter(isHttpInteraction)
  64. export const webSocketInteractions = (interactions: ReadonlyArray<Interaction>) =>
  65. interactions.filter(isWebSocketInteraction)
  66. export const CassetteSchema = Schema.Struct({
  67. version: Schema.Literal(1),
  68. metadata: Schema.optional(CassetteMetadataSchema),
  69. interactions: Schema.Array(InteractionSchema),
  70. })
  71. export type Cassette = Schema.Schema.Type<typeof CassetteSchema>
  72. export const decodeCassette = Schema.decodeUnknownSync(CassetteSchema)
  73. export const encodeCassette = Schema.encodeSync(CassetteSchema)