assertions.ts 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import type { CallResult, JsonObject } from "./types"
  2. export function parse(text: string): unknown {
  3. if (!text) return undefined
  4. try {
  5. return JSON.parse(text) as unknown
  6. } catch {
  7. return text
  8. }
  9. }
  10. export function looksJson(result: CallResult) {
  11. return result.contentType.includes("application/json") || result.text.startsWith("{") || result.text.startsWith("[")
  12. }
  13. export function stable(value: unknown): string {
  14. return JSON.stringify(sort(value))
  15. }
  16. function sort(value: unknown): unknown {
  17. if (Array.isArray(value)) return value.map(sort)
  18. if (!value || typeof value !== "object") return value
  19. return Object.fromEntries(
  20. Object.entries(value)
  21. .sort(([left], [right]) => left.localeCompare(right))
  22. .map(([key, item]) => [key, sort(item)]),
  23. )
  24. }
  25. export function array(value: unknown): asserts value is unknown[] {
  26. if (!Array.isArray(value)) throw new Error("expected array")
  27. }
  28. export function object(value: unknown): asserts value is JsonObject {
  29. if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error("expected object")
  30. }
  31. export function boolean(value: unknown): asserts value is boolean {
  32. if (typeof value !== "boolean") throw new Error("expected boolean")
  33. }
  34. export function isRecord(value: unknown): value is JsonObject {
  35. return !!value && typeof value === "object" && !Array.isArray(value)
  36. }
  37. export function check(value: boolean, message: string): asserts value {
  38. if (!value) throw new Error(message)
  39. }
  40. export function message(error: unknown) {
  41. if (error instanceof Error) return error.message
  42. return String(error)
  43. }
  44. export function pad(value: string, size: number) {
  45. return value.length >= size ? value : value + " ".repeat(size - value.length)
  46. }
  47. export function indent(value: string) {
  48. return value
  49. .split("\n")
  50. .map((line) => ` ${line}`)
  51. .join("\n")
  52. }