All files / web/src/lib/abacus/print browser-transport.ts

90.19% Statements 46/51
100% Branches 14/14
66.66% Functions 2/3
90.19% Lines 46/51

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 521x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 8x 8x 8x 8x 8x 1x 1x 1x 1x 1x 1x 7x 8x 8x 8x 8x 8x 8x 8x 8x 8x 7x 1x 1x 1x            
/**
 * Browser transport for `@eink/print-dialog`'s client (Phase 2b, Gitea #9).
 *
 * The kit's `TransportFetch` is structural (it compiles with no DOM lib), so
 * the browser side supplies this tiny adapter over the real `fetch`. Auth and
 * tenancy live entirely here, at the kit's designed seam: requests go to
 * abaci's own proxy (`/api/abacus/print/*`) with the session cookie, and the
 * `?connectionId=` selector rides as a query param so the kit's `basePath`
 * stays a plain prefix. The kit does its own ETag revalidation, so the HTTP
 * cache is bypassed (`no-store`) — one caching layer, not two.
 */
import {
  createPrintServiceClient,
  type PrintServiceClient,
  type TransportFetch,
} from '@eink/print-dialog'
 
/** The proxy prefix all print-service reads go through. */
export const PRINT_PROXY_BASE_PATH = '/api/abacus/print'
 
/** Append `connectionId` to a URL that may or may not already have a query. */
function withConnectionId(url: string, connectionId: string | undefined): string {
  if (!connectionId) return url
  const sep = url.includes('?') ? '&' : '?'
  return `${url}${sep}connectionId=${encodeURIComponent(connectionId)}`
}
 
/**
 * A `TransportFetch` over the browser's `fetch`, scoped to one connection.
 * Omit `connectionId` to let the proxy fall back to the user's sole connection.
 */
export function createProxyTransportFetch(connectionId?: string): TransportFetch {
  return (url, init) =>
    fetch(withConnectionId(url, connectionId), {
      method: init?.method,
      headers: init?.headers ? { ...init.headers } : undefined,
      // The kit's abort semantics detach the caller rather than cancel the
      // request; only forward a signal that is a real DOM AbortSignal.
      signal: init?.signal instanceof AbortSignal ? init.signal : undefined,
      credentials: 'same-origin',
      cache: 'no-store',
    })
}
 
/** The package client aimed at abaci's proxy for one connection. */
export function createAbacusPrintClient(connectionId?: string): PrintServiceClient {
  return createPrintServiceClient({
    fetch: createProxyTransportFetch(connectionId),
    basePath: PRINT_PROXY_BASE_PATH,
  })
}