Skip to main content
jg-packages

Search

    API envelopes

    jg-api-response

    Build and recognise the success, data, and error envelope that services exchange over HTTP, with errors as a code, a message, and data.

    v1.1.1UniversalESMMIT

    npm install jg-api-response

    Usage

    Build the body a service responds with. A response is successful when no error is passed:

    ts
    import { buildResponse } from 'jg-api-response';
    
    buildResponse({ id: 1 });
    // { success: true, data: { id: 1 }, error: null }

    A failed response carries the error as { code, message, data }, so the client gets everything it needs to handle or debug it. An Exception from jg-exception keeps its code, message, and data:

    ts
    import { Exception } from 'jg-exception';
    
    buildResponse(
      undefined,
      new Exception('The user was not found.', { code: 'USER_NOT_FOUND', data: { id: 1 } }),
    );
    // {
    //   success: false,
    //   data: undefined,
    //   error: { code: 'USER_NOT_FOUND', message: 'The user was not found.', data: { id: 1 } },
    // }

    Any other error keeps its string code, such as a Node.js ENOENT, or gets UNKNOWN_ERROR, with its message and null data:

    ts
    buildResponse(undefined, new Error('Request failed'));
    // { success: false, data: undefined, error: { code: 'UNKNOWN_ERROR', message: 'Request failed', data: null } }

    The envelope can always be serialized when its data can: Exception data that JSON can’t hold becomes null.

    Check a body you received, after JSON.parse dropped its undefined fields, or from a service that leaves out error or its data:

    ts
    import { isResponse } from 'jg-api-response';
    
    const body: unknown = await response.json();
    if (isResponse<IUser>(body)) {
      body.success; // boolean
      body.data; // IUser | undefined
      body.error; // { code: string; message: string; data?: unknown } | null | undefined
    }

    isResponse checks the error’s code and message, but not its data, which is unknown until you check it.

    Generated from TSDoc

    API reference

    Every export of [email protected], 6 in all, with its signature, its errors, and an example.

    Functions

    buildResponse

    function

    Builds the envelope for an HTTP body. The response is successful when no error is passed. Any error that is passed, even a falsy one, becomes { code, message, data }: an Exception keeps all three, and any other error keeps its string code, or gets UNKNOWN_ERROR, and its message. A failed response can carry data too.

    Signature
    buildResponse<T = undefined>(data?: T, error?: unknown): IApiResponse<T>

    Parameters

    data?T

    The data to send.

    error?unknown

    The error the request failed with, of any shape.

    Returns

    IApiResponse<T>

    The envelope, which JSON.stringify can always serialize when the data can.

    Example
    import { buildResponse } from 'jg-api-response';
    import { Exception } from 'jg-exception';
    
    buildResponse({ id: 1 }); // => { success: true, data: { id: 1 }, error: null }
    buildResponse(undefined, new Exception('Not found', { code: 'NOT_FOUND', data: { id: 1 } }));
    // { success: false, data: undefined, error: { code: 'NOT_FOUND', message: 'Not found', data: { id: 1 } } }

    isResponse

    function

    Checks whether a value is an envelope, including one parsed from JSON or sent by another service: an object with a boolean success, an error that is null, missing, or an object with a string code and message, and any data or none. The error's data isn't checked.

    Signature
    isResponse<T>(value: unknown): value is IParsedApiResponse<T>

    Parameters

    valueunknown

    The value to check, such as a parsed response body.

    Returns

    value is IParsedApiResponse<T>

    Whether the value is an envelope.

    Example
    import { isResponse } from 'jg-api-response';
    
    type IUser = { id: number; name: string };
    
    const body: unknown = JSON.parse('{"success":true,"data":{"id":1,"name":"Ada"},"error":null}');
    isResponse<IUser>(body); // => true
    if (isResponse<IUser>(body) && body.success) {
      body.data; // IUser | undefined
    }

    Types

    IApiError

    type

    an error as an envelope carries it to the client

    Declaration
    type IApiError = {
        code: string;
        message: string;
        data: IJsonValue;
    };

    Members

    • codeproperty
      string

      the stable code the client handles the error by, or UNKNOWN_ERROR when the error had none

    • messageproperty
      string

      what failed

    • dataproperty
      IJsonValue

      the context the error carried, or null when it carried none

    IApiResponse

    type

    The envelope a service sends in an HTTP body. A response is successful when it has no error, and it carries data either way.

    Declaration
    type IApiResponse<T> = {
        success: boolean;
        data: T;
        error: IApiError | null;
    };

    Members

    • successproperty
      boolean

      whether the request succeeded, which is when error is null

    • dataproperty
      T

      the data sent to the client, whatever the outcome

    • errorproperty
      IApiError | null

      the error the request failed with, or null when it succeeded

    IParsedApiError

    type

    An envelope error as it arrives from any service. data may be missing, and it's unknown, because isResponse doesn't check it: whoever reads it checks it first.

    Declaration
    type IParsedApiError = {
        code: string;
        message: string;
        data?: unknown;
    };

    Members

    • codeproperty
      string
    • messageproperty
      string
    • dataproperty
      unknown

    IParsedApiResponse

    type

    An envelope as it arrives after JSON.parse: undefined fields are gone, and services may send error: null on success or leave error out.

    Declaration
    type IParsedApiResponse<T> = {
        success: boolean;
        data?: T;
        error?: IParsedApiError | null;
    };

    Members

    • successproperty
      boolean
    • dataproperty
      T
    • errorproperty
      IParsedApiError | null