All files / src/utils/typeGuards labchem.ts

100% Statements 37/37
100% Branches 3/3
100% Functions 3/3
100% Lines 37/37

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 961x             1x 1x 1x 1x 1x 1x 1x   1x 1x   1x 1x 1x 1x 1x 1x   1x   1x 1x 1x 1x 1x                               1x 1x 1x 1x   1x                               1x 1x 2x   2x 2x   1x                               1x 1x 4x 4x  
import * as v from 'valibot';
import type {
  EpagesProductPage,
  EpagesSearchResponse,
  EpagesVariationsResponse,
} from '@/types/labchem';
 
const epagesSearchResponseSchema = v.object({
  products: v.array(
    v.looseObject({
      productId: v.string(),
      name: v.string(),
      links: v.array(v.looseObject({ rel: v.string(), href: v.string() })),
    }),
  ),
  totalNumberOfProducts: v.number(),
});
 
const epagesVariationsResponseSchema = v.object({
  results: v.number(),
  items: v.array(
    v.looseObject({
      link: v.looseObject({ rel: v.string(), href: v.string() }),
    }),
  ),
});
 
const epagesProductPageSchema = v.looseObject({
  productId: v.string(),
  forSale: v.boolean(),
});
/**
 * Type guard for the ePages catalog search response
 * (`POST /api/v2/search`). Verifies the `products` array (each with an id, name,
 * and links) and the `totalNumberOfProducts` count used to drive pagination.
 *
 * @category Typeguards
 * @param response - The value to validate
 * @returns Type predicate indicating whether `response` is an EpagesSearchResponse
 * @example
 * ```typescript
 * const json = await httpPostJson({ path: "/api/v2/search", body: { query: "" } });
 * if (isEpagesSearchResponse(json)) {
 *   console.log(`${json.totalNumberOfProducts} products in catalog`);
 * }
 * ```
 * @source
 */
export function isEpagesSearchResponse(response: unknown): response is EpagesSearchResponse {
  return v.safeParse(epagesSearchResponseSchema, response).success;
}
 
/**
 * Type guard for a master product's variations list
 * (`GET …/products/{masterId}/variations`). Verifies the `items` array, each
 * entry carrying a `link` to its variation product page.
 *
 * @category Typeguards
 * @param response - The value to validate
 * @returns Type predicate indicating whether `response` is an EpagesVariationsResponse
 * @example
 * ```typescript
 * const json = await httpGetJson({ path: `/rs/shops/${shopId}/products/${id}/variations` });
 * if (isEpagesVariationsResponse(json)) {
 *   const purchasable = json.items.filter((i) => i.additionalAttributes?.purchasable !== false);
 * }
 * ```
 * @source
 */
export function isEpagesVariationsResponse(
  response: unknown,
): response is EpagesVariationsResponse {
  return v.safeParse(epagesVariationsResponseSchema, response).success;
}
 
/**
 * Type guard for a per-variation (or master) product page (`GET …/products/{id}`).
 * Verifies the fields the enrichment step reads first — `productId` and the
 * `forSale` stock flag.
 *
 * @category Typeguards
 * @param response - The value to validate
 * @returns Type predicate indicating whether `response` is an EpagesProductPage
 * @example
 * ```typescript
 * const json = await httpGetJson({ path: variation.link.href });
 * if (isEpagesProductPage(json) && json.forSale) {
 *   console.log(json.priceInfo?.price?.amount);
 * }
 * ```
 * @source
 */
export function isEpagesProductPage(response: unknown): response is EpagesProductPage {
  return v.safeParse(epagesProductPageSchema, response).success;
}