All files / src/utils/address serialize.ts

55.55% Statements 5/9
60% Branches 6/10
33.33% Functions 2/6
55.55% Lines 5/9

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150                                                                                                            529x                                                                                                                                         65x 58x     7x             7x                              
import { AddressType } from "@validation/schemas/address";
 
/**
 * Serializes canonical Address to API format.
 *
 * Most APIs expect the address in this format with "line1" as the street field.
 * This is the default serializer for business owner and merchant APIs.
 *
 * @param address - Canonical Address object
 * @returns API-compatible address object
 */
export function serializeAddressForAPI(address: AddressType) {
  return {
    line1: address.line1,
    city: address.city,
    state: address.state,
    zip: address.zip,
    country: address.country,
  };
}
 
/**
 * Serializes canonical Address to legacy "street" format.
 *
 * Some older APIs/components expect "street" instead of "line1".
 * Use this serializer for those specific cases.
 *
 * @param address - Canonical Address object
 * @returns Address object with "street" field
 */
export function serializeAddressWithStreet(address: AddressType) {
  return {
    street: address.line1,
    city: address.city,
    state: address.state,
    zip: address.zip,
    country: address.country,
  };
}
 
/**
 * Serializes canonical Address to business address info format.
 *
 * TBusinessAddressInfo has a quirk: the field named "address" contains just the street.
 * This serializer handles that specific case.
 *
 * @param address - Canonical Address object
 * @param notes - Optional notes field for business addresses
 * @returns TBusinessAddressInfo-compatible object
 */
export function serializeBusinessAddressInfo(
  address: AddressType,
  notes?: string,
) {
  return {
    address: address.line1, // Field named "address" contains street only!
    city: address.city,
    state: address.state,
    zip: address.zip,
    country: address.country,
    ...(notes && { notes }),
  };
}
 
/**
 * Serializes canonical Address with both "line1" AND "street" fields.
 *
 * Some APIs/payloads need both fields for backward compatibility.
 * This serializer populates both with the same value.
 *
 * @param address - Canonical Address object
 * @returns Address object with both line1 and street
 */
export function serializeAddressWithBothFields(address: AddressType) {
  return {
    line1: address.line1,
    street: address.line1, // Duplicate for backward compatibility
    city: address.city,
    state: address.state,
    zip: address.zip,
    country: address.country,
  };
}
 
/**
 * Serializes canonical Address to flat structure (no nesting).
 *
 * Some components/APIs expect address fields at the root level.
 * This flattens the address onto the parent object.
 *
 * @param address - Canonical Address object
 * @param parentData - Parent object to merge address fields into
 * @returns Parent object with flattened address fields
 *
 * @example
 * const payload = serializeFlatAddress(address, { firstName: "John" });
 * // Returns: { firstName: "John", line1: "123 Main", city: "NYC", ... }
 */
export function serializeFlatAddress<T extends Record<string, any>>(
  address: AddressType,
  parentData?: T,
): T & ReturnType<typeof serializeAddressForAPI> {
  return {
    ...(parentData || {}),
    ...serializeAddressForAPI(address),
  } as T & ReturnType<typeof serializeAddressForAPI>;
}
 
/**
 * Formats address as a display string.
 *
 * Replaces the old formatAddress utility with consistent behavior.
 *
 * @param address - Canonical Address object
 * @returns Formatted address string
 *
 * @example
 * formatAddressDisplay(address)
 * // Returns: "123 Main St, New York, NY 10001, US"
 */
export function formatAddressDisplay(
  address: AddressType | null | undefined,
): string {
  if (!address || !address.city) {
    return "";
  }
 
  const parts = [
    address.line1,
    `${address.city}${address.state ? `, ${address.state}` : ""}`,
    address.zip,
    address.country,
  ].filter(Boolean);
 
  return parts.join(" ");
}
 
/**
 * Type definitions for serialized address formats
 * These help with type safety when working with different API shapes
 */
export type APIAddress = ReturnType<typeof serializeAddressForAPI>;
export type StreetAddress = ReturnType<typeof serializeAddressWithStreet>;
export type BusinessAddressInfo = ReturnType<
  typeof serializeBusinessAddressInfo
>;
export type DualFieldAddress = ReturnType<
  typeof serializeAddressWithBothFields
>;