Skip to content

Request (StrataRequest)

The StrataRequest class represents a request throughout its entire lifecycle -- from the moment it arrives to when the response is sent. It holds both the incoming request data and the outgoing response data. This is the object your operation handlers receive, and what middleware operates on.

typescript
import { StrataRequest } from '@strata-js/strata';

// Also exported as `Request` for convenience
import { Request } from '@strata-js/strata';

Type Parameters

typescript
class StrataRequest<
    PayloadType = Record<string, unknown>,
    MetadataType = Record<string, unknown>,
    ResponsePayloadType = Record<string, unknown>
>

All three type parameters default to Record<string, unknown>.

Request Properties

These are set when the request is created and are read-only.

PropertyTypeDescription
idstringUnique request identifier.
contextstringTarget context name.
operationstringTarget operation name.
payloadPayloadTypeApplication-specific request data.
metadataMetadataTypeAdditional metadata (tracking, stats, etc.).
authstring | undefinedAuthentication data (typically a JWT).
clientstringHuman-readable client identifier.
messageType'request' | 'post'Whether this is a request (expects response) or a post (fire-and-forget).
timestampstringISO 8601 datetime of when the request was created.
receivedTimestampnumberDate.now() when the request was received by the service.
responseQueuestring | undefinedQueue for sending the response (set by the backend). Only on requests, not posts.
timeoutnumber | undefinedTimeout in milliseconds. Only on requests, not posts.
priorRequeststring | undefinedID of the request that triggered this one.
requestChainstring[]Chain of request IDs for distributed tracing.

Response Properties

These are populated as the request is processed.

PropertyTypeDescription
status'pending' | 'succeeded' | 'failed'Current request status.
responseResponsePayloadType | undefinedThe response payload, set by succeed() or fail().
completedTimestampnumber | undefinedDate.now() when the request was completed.
servicestring | undefinedIdentifier of the service that processed this.
messagesResponseMessage[]Structured messages generated during processing.

Internal Properties

PropertyTypeDescription
promisePromise<void>Resolves when the request is succeeded or failed. Used internally for tracking.

Methods

succeed()

typescript
request.succeed(payload : ResponsePayloadType) : void

Marks the request as succeeded with the given payload. Sets status to 'succeeded', records the completedTimestamp, and resolves the internal promise.

typescript
// In an operation handler
context.registerOperation('get', async (request) =>
{
    const user = await db.findUser(request.payload.userId);
    request.succeed({ user });
});

TIP

If your handler returns a value without calling succeed() or fail(), Strata automatically calls succeed() with the return value.

fail()

typescript
request.fail(reason : string | Error | ResponsePayloadType) : void

Marks the request as failed. Sets status to 'failed', records the completedTimestamp, and resolves the internal promise. The reason determines the response payload:

Reason TypeBehavior
ServiceErrorSerialized via toJSON() -- includes name, message, code, isSafeMessage, stack.
ErrorWrapped into { message, name: 'FailedRequestError', stack, code, details, isSafeMessage }.
stringWrapped into { message: reason, name: 'FailedRequestError', code: 'FAILED_REQUEST' }.
objectUsed directly as the response payload.
typescript
// Fail with a string
request.fail('User not found');

// Fail with an Error
request.fail(new Error('Database connection lost'));

// Fail with a ServiceError (includes isSafeMessage for client-visible errors)
import { errors } from '@strata-js/strata';
request.fail(new errors.ServiceError('User not found', 'USER_NOT_FOUND'));

// Fail with a custom payload
request.fail({ message: 'Validation failed', errors: [ 'name is required' ] });

renderRequest()

typescript
request.renderRequest() : RequestEnvelope<PayloadType, MetadataType>

Serializes the request into its wire format -- a plain RequestEnvelope object with no methods. Useful for logging, debugging, or creating clones.

typescript
const envelope = request.renderRequest();
console.log(JSON.stringify(envelope, null, 2));

renderResponse()

typescript
request.renderResponse() : ResponseEnvelope<ResponsePayloadType>

Serializes the response into its wire format -- a plain ResponseEnvelope object with no methods.

typescript
const envelope = request.renderResponse();
console.log(envelope.status);   // 'succeeded' or 'failed'
console.log(envelope.payload);  // the response payload
console.log(envelope.messages); // any ResponseMessage objects

parseResponse()

typescript
request.parseResponse(response : ResponseEnvelope<ResponsePayloadType>) : void

Populates this request's response properties from a received ResponseEnvelope. Used internally by the client when a response arrives over the wire. Calls succeed() or fail() based on the envelope's status.

Working with Messages

The messages array on a request holds ResponseMessage objects. You can push messages onto this array during processing to include warnings, info, or debug details in the response -- even on successful requests.

typescript
context.registerOperation('create', async (request) =>
{
    const user = await db.createUser(request.payload);

    if(user.emailUnverified)
    {
        request.messages.push({
            severity: 'warning',
            message: 'Email address has not been verified.',
            code: 'EMAIL_UNVERIFIED',
        });
    }

    return { user };
});

See ResponseMessage for the full interface.

Lifecycle

  1. A request arrives and a StrataRequest is constructed with status: 'pending'.
  2. Global beforeRequest() middleware runs.
  3. Context beforeRequest() middleware runs.
  4. Operation beforeRequest() middleware runs.
  5. If still 'pending', the operation handler executes.
  6. If the handler returns a value and the request is still 'pending', succeed() is called with the return value.
  7. If the request succeeded, success() middleware runs (operation -> context -> global).
  8. If the request failed, failure() middleware runs (operation -> context -> global).
  9. The response is rendered and sent back via the backend.

At any point, middleware can short-circuit by calling request.succeed() or request.fail() directly. See Middleware Model for details.