MCPcopy Create free account
hub / github.com/TestSprite/testsprite-cli / requestWithMeta

Method requestWithMeta

src/lib/http.ts:407–610  ·  view source on GitHub ↗
(
    method: string,
    path: string,
    options: RequestOptions = {},
  )

Source from the content-addressed store, hash-verified

405 }
406
407 async requestWithMeta<T>(
408 method: string,
409 path: string,
410 options: RequestOptions = {},
411 ): Promise<RequestResult<T>> {
412 if (!this.apiKey) throw ApiError.authRequired();
413
414 const url = buildUrl(this.baseUrl, path, options.query);
415 const requestId = options.requestId ?? newRequestId();
416
417 let attempt = 0;
418 while (true) {
419 attempt += 1;
420 this.debug({ kind: 'request', method, url, attempt, requestId });
421 const startedAt = Date.now();
422 let response: Response;
423
424 // Compose the per-request timeout signal with any caller-supplied signal.
425 // The fetch aborts on whichever fires first. This ensures every one-shot
426 // request (test create/update/delete/list/get, auth whoami, code put/get,
427 // plan put) has a client-side deadline even when the caller supplies no
428 // signal. The polling path supplies its own deadline-aware signal per
429 // iteration — this timeout (120s default) is safely larger than any single
430 // long-poll window (<=25s via ?waitSeconds), so it never bites polling.
431 const timeoutSignal = AbortSignal.timeout(this.requestTimeoutMs);
432 const effectiveSignal =
433 options.signal != null ? AbortSignal.any([timeoutSignal, options.signal]) : timeoutSignal;
434
435 try {
436 response = await this.fetchImpl(url, {
437 method,
438 headers: this.buildHeaders(requestId, options),
439 body: options.body !== undefined ? JSON.stringify(options.body) : undefined,
440 signal: effectiveSignal,
441 });
442 } catch (err) {
443 // Distinguish a client-side request timeout from a caller-supplied abort.
444 //
445 // Node 22 `AbortSignal.timeout()` throws a `DOMException` with
446 // `name === 'TimeoutError'` (not 'AbortError') when the signal fires.
447 // A caller-supplied abort sets `name === 'AbortError'`.
448 // We treat both abort variants together: if the timeout signal fired and
449 // the caller hadn't already aborted, surface a clear RequestTimeoutError.
450 // A timeout/abort during the fetch itself: classify it (RequestTimeoutError
451 // when our deadline fired; otherwise rethrow the caller's abort unmodified).
452 this.rethrowIfAbort(err, timeoutSignal, options.signal, requestId);
453 // If a RequestTimeoutError already propagated from somewhere (e.g. from a
454 // nested call or from a test-injected fetchImpl), pass it through unchanged
455 // rather than re-wrapping it as a TransportError.
456 if (err instanceof RequestTimeoutError) throw err;
457 const message = err instanceof Error ? err.message : String(err);
458 this.debug({
459 kind: 'error',
460 method,
461 url,
462 attempt,
463 requestId,
464 errorCode: 'TRANSPORT',

Callers 11

getMethod · 0.95
postMethod · 0.95
putMethod · 0.95
patchMethod · 0.95
deleteMethod · 0.95
getWithMetaMethod · 0.95
postWithMetaMethod · 0.95
putWithMetaMethod · 0.95
patchWithMetaMethod · 0.95
deleteWithMetaMethod · 0.95
requestMethod · 0.95

Calls 15

debugMethod · 0.95
buildHeadersMethod · 0.95
rethrowIfAbortMethod · 0.95
transitionMethod · 0.95
buildUrlFunction · 0.85
newRequestIdFunction · 0.85
transportRetryDecisionFunction · 0.85
shortPathFunction · 0.85
safeReadJsonFunction · 0.85
isTransportEdgeStatusFunction · 0.85
parseRetryAfterFunction · 0.85
apiRetryDecisionFunction · 0.85

Tested by

no test coverage detected