~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
69 lines · 2.2 KB Raw History
/**
 * One record value as an indented key/value tree: keys and nesting carry the
 * structure, with none of JSON's brace and quote noise. Image blobs render as
 * a thumbnail when a `blobBase` URL is given.
 */
export function RecordValue({ value, blobBase }) {
  if (value === null || value === undefined)
    return <span className="text-muted">null</span>;
  if (typeof value === 'string')
    return value === '' ? (
      <span className="text-muted">""</span>
    ) : (
      <span className="whitespace-pre-wrap break-words text-foreground">
        {value}
      </span>
    );
  if (typeof value === 'number')
    return <span className="text-number">{value}</span>;
  if (typeof value === 'boolean')
    return <span className="text-success">{String(value)}</span>;

  if (Array.isArray(value)) {
    return value.map((item, index) => (
      // biome-ignore lint/suspicious/noArrayIndexKey: records have no ids
      <div key={index} className="flex gap-1.5">
        <span className="shrink-0 text-faint">-</span>
        <div className="min-w-0 flex-1">
          <RecordValue value={item} blobBase={blobBase} />
        </div>
      </div>
    ));
  }

  const thumbnail =
    blobBase &&
    value.$type === 'blob' &&
    typeof value.ref?.$link === 'string' &&
    value.mimeType?.startsWith('image/')
      ? `${blobBase}&cid=${encodeURIComponent(value.ref.$link)}`
      : null;

  return (
    <>
      {thumbnail && (
        <img
          src={thumbnail}
          alt=""
          className="my-1 block max-h-40 max-w-40 rounded-md border border-border"
        />
      )}
      {Object.entries(value).map(([key, inner]) => {
        const nested = inner !== null && typeof inner === 'object';
        return nested ? (
          <div key={key}>
            <span className="text-key">{key}:</span>
            <div className="ml-[2ch]">
              <RecordValue value={inner} blobBase={blobBase} />
            </div>
          </div>
        ) : (
          <div key={key} className="flex gap-1.5">
            <span className="shrink-0 text-key">{key}:</span>
            <RecordValue value={inner} blobBase={blobBase} />
          </div>
        );
      })}
    </>
  );
}