Skip to main content

Request meta

Single-object methods return the bare object. The metadata you'd need from the envelope — requestId, timestamp, list pagination — lives on cstar.lastMeta right after the call. Reach for it when you need it; ignore it when you don't.

The shape

Read it right after the call

lastMeta is mutable and overwritten on every request. Read it on the line after the awaited call, or capture it into a local before the next call fires.

capture-meta.js
const ticket = await cstar.tickets.create({ title: 'Help' });

// Right here — meta is fresh
const requestId = cstar.lastMeta.requestId;
const createdAt = cstar.lastMeta.timestamp;

log.info('ticket created', { id: ticket.id, requestId, createdAt });

// On a list call, pagination lands too
const { data } = await cstar.tickets.list({ status: 'open' });
console.log(cstar.lastMeta.pagination); // { total, page, pageSize, hasMore }

Wrap the SDK with logging

Every team eventually wants per-call logs. lastMeta makes that a one-liner around each method call.

logged-cstar.js
function trace(fn, label) {
  return async (...args) => {
    const start = Date.now();
    try {
      const result = await fn(...args);
      log.info(label, {
        ms: Date.now() - start,
        requestId: cstar.lastMeta.requestId
      });
      return result;
    } catch (e) {
      log.error(label, {
        ms: Date.now() - start,
        requestId: e.requestId, // CStarError exposes this directly
        code: e.code
      });
      throw e;
    }
  };
}

const createTicket = trace((p) => cstar.tickets.create(p), 'tickets.create');
await createTicket({ title: 'Help' });

Why side-channel and not envelope?

See "Bare resources, not envelopes" on the principles page — short version: most callers want the object, so the SDK gives you the object and parks the metadata on the side. Lists are the exception because the page numbers are part of the answer, not metadata about it.

Next up