0.74.2 • Published 3 years ago

@bumped-inc/bumped-api-client v0.74.2

Weekly downloads
-
License
UNLICENSED
Repository
github
Last release
3 years ago

@bumped-inc/bumped-api-client

Client to fetch data from the Bumped API

About

The API for the Bumped-API-Client has had breaking changes, relatively often. As we pin down our patterns, these have become and will continue to become less frequent.

The primary places the Bumped-API-Client are used are in bumped-web, and some light usage within bumped.com. It is likely that it will be used in some form in bumped-app. It could also be used for end-to-end tests.

Guidelines for development

The most important aspect to prioritize of the Bumped-API-Client is internal consistency. As a user of the client, there should be the least amount of surprises possible.

Updating generated types for GraphQL API

If there is a change to the GraphQL API Schema, then schema references must be updated via

$ yarn add --dev @bumped-inc/graphql-schema-artifacts

And then it is recommended to run

$ yarn run relay

Which will use the new schema to generate relevant types. One may first need to make changes to GraphQL queries or mutations before any change is apparent.

Updating generated code and types for REST API

If there is a change to the REST API, then the OpenAPI spec must be updated via

$ cd external/api-specs
$ git pull
$ cd ../..
$ yarn run update-api-yml
$ yarn run generate-rest-client

This should update the git submodule within external/api-specs to the most recently-published version, then copy the OpenAPI spec to an appropriate local path, then use that to generate new code and types via openapi-generator.

Input types

All input types are plain objects. They may contain non-plain properties which may be converted into something more usable before it goes across the wire, but that is intentionally obfuscated from the caller.

If an object can be empty, undefined is also accepted as an input, for convenience's sake.

When defining an input interface type, the name is typically the PascalCase version of the function name with the Input suffix. e.g. getOffer -> GetOfferInput.

If there are no properties that would be useful for an input interface type (including optional ones), then undefined should explicitly be used and an interface should not be unnecessarily defined.

As time progresses, a new data requirement may be added to an existing request. If more input data is required, that is typically denoted as a new property on the Input interface. If it is optional, then this is generally not considered a breaking change.

Output types

Output types fall into one of two categories, with no exceptions:

  • void (represented as undefined at runtime), which implies that there is no useful information to retrieve from the network upon successful completion of the request. Whether the request resolves or rejects is the only needed information.
  • A plain object, which has one or more properties that can provide useful information to the caller. This should never be an array, as that is less extensible and not future-proof.

When defining an input interface type, the name is typically the PascalCase version of the function name with the Payload suffix. e.g. getOffer -> GetOfferPayload, but may be a simpler type such as Offer itself.

New data requirements may be added to an existing request. These should be either a new property on the Payload interface or changes to the internal types of said interface. Adding new data in this way should almost never be a breaking change.

Pagination

Pagination is accounted for by the addition of two input properties and an extra output property.

  • input readonly limit?: number;

    Specifies the maximum amount of items per page. Do not alter this between calls when using the same cursor.

  • input readonly after?: ID<'ListDocumentsCursor'>;

    Specifies the cursor of the last page that was seen. When requesting the first page, this should be undefined. All subsequent pages have that starting cursor, which can be seen like a bookmark.

  • output readonly nextPage: ID<'ListDocumentsCursor'> | null;

    Specifies the cursor that can be provided as the after property for the next call. If null, then there are no more pages to return.

More, pagination-specific properties may be provided, on a per-request basis, such as the total count of items or facet information about a search query. Those may be useful and informative, but only the above three properties are required in order to support pagination.

Naming

For exported functions which will result in one or more network requests, use standard action tense for function naming, without unnecessary suffixes such as Async or Promise or Request.

When querying data in a non-mutative way, starting with the word get is a safe choice.

When querying paginated data, instead prefer to start with the word list. Stipulation: if querying a list of items that are not paginated, do not start with the word list.

When sending a mutative request, start with a relevant action verb such as add, remove, create, or update. Whatever word is chosen, it should be obvious that it is making a change and ideally obvious about what it intends to do.

Documentation

Documentation should be put on all public exports, including type exports.

Public documentation generally exists in one of three areas:

  • On an exported function:

    JSDoc should be used, and speak of the function in the active tense, e.g. "Subscribes to a particular notification."

    Because the input type and output type should be fully-documented interfaces themselves, they can often go unmentioned within the function documentation.

  • On an input type:

    Each property should be documented and provide a reasonable description for what that property does. If it is optional, either be explicit about what the undefined case means or explicitly call out the default value using the @default syntax.

    If a property type is a disjoint union, it is likely that each possible type within the union needs full documentation.

    If a property type is an object itself, each of its properties should be documented in standard JSDoc fashion.

  • On an output type:

    Follow the same direction for input types, but the phrasing should be directed at someone who will be using and observing the output type as something to read from rather than to construct and provide.

    Be explicit about what undefined or null means if they are possibilities.

Pitfalls to avoid

  • Do not manually define generated interfaces. If you are trying to define an object type that comes from an API, that should be generated by an automated tool and not maintained manually. (Note: this does not apply to enum definitions: see the Enums section below.)

    A corrolary to this is that it is perfectly fine to define type aliases of generated types, including reaching into a generated type to retrieve one that would not otherwise be easily-accessible.

Enums

Do not re-use enums that are generated either from the REST client or the GraphQL generated code, as these tend to have subpar documentation and are typically not in the best form to use from external usage.

Instead, define an enum with other types (in a types.ts file, likely), where each key is a legibile PascalCase name. Do not define this as a const enum, as that can cause problems in some environments. The values can match the values of the generated enum, though.

Also, for each defined enum, define a function that starts with is to allow for easy verification.

For example, for an ActivityType enum, the following should be declared immediately after definition:

/**
 * Returns whether `value` is an `ActivityType`
 *
 * @param value The value to check, which should probably be a string
 */
export const isActivityType = createIsEnumValue(ActivityType);

With this, when mapping a response payload to a return type, the following pattern can be used:

function mapResponse({ activityType }) {
  return {
    activityType: isActivityType(activityType)
      ? activityType
      : ActivityType.SomeSaneDefault,
  };
}
0.74.0

3 years ago

0.74.2

3 years ago

0.74.1

3 years ago

0.70.2

3 years ago

0.71.0

3 years ago

0.72.0

3 years ago

0.73.0

3 years ago

0.70.0

3 years ago

0.70.1

3 years ago

0.69.1

3 years ago

0.69.0

3 years ago

0.68.5

3 years ago

0.68.4

3 years ago

0.68.3

3 years ago

0.68.2

3 years ago

0.68.1

3 years ago

0.67.0

3 years ago

0.68.0

3 years ago

0.66.0

3 years ago

0.64.2

3 years ago

0.65.2

3 years ago

0.65.1

3 years ago

0.65.3

3 years ago

0.65.0

3 years ago

0.64.1

3 years ago

0.64.0

3 years ago

0.63.0

3 years ago

0.62.1

3 years ago

0.62.0

3 years ago

0.62.3

3 years ago

0.62.2

3 years ago

0.59.0

3 years ago

0.60.1

3 years ago

0.60.0

3 years ago

0.61.0

3 years ago

0.55.0

3 years ago

0.56.0

3 years ago

0.57.4

3 years ago

0.57.5

3 years ago

0.57.2

3 years ago

0.57.3

3 years ago

0.57.0

3 years ago

0.57.1

3 years ago

0.57.6

3 years ago

0.58.1

3 years ago

0.58.0

3 years ago

0.54.0

3 years ago

0.53.0

3 years ago

0.51.0

3 years ago

0.52.0

3 years ago

0.50.1

3 years ago

0.50.0

3 years ago

0.49.8

3 years ago

0.49.7

3 years ago

0.49.6

3 years ago

0.49.5

3 years ago

0.49.3

3 years ago

0.49.4

3 years ago

0.49.1

3 years ago

0.49.2

3 years ago

0.49.0

3 years ago

0.48.3

3 years ago

0.48.2

3 years ago

0.48.0

3 years ago

0.48.1

3 years ago

0.43.0

3 years ago

0.36.2

3 years ago

0.36.1

3 years ago

0.36.0

3 years ago

0.32.0

3 years ago

0.44.0

3 years ago

0.29.1

3 years ago

0.40.2

3 years ago

0.40.3

3 years ago

0.40.0

3 years ago

0.40.1

3 years ago

0.37.0

3 years ago

0.33.0

3 years ago

0.41.5

3 years ago

0.41.3

3 years ago

0.45.0

3 years ago

0.41.4

3 years ago

0.41.1

3 years ago

0.41.2

3 years ago

0.41.0

3 years ago

0.38.1

3 years ago

0.38.0

3 years ago

0.34.2

3 years ago

0.34.1

3 years ago

0.34.0

3 years ago

0.30.0

3 years ago

0.46.0

3 years ago

0.46.1

3 years ago

0.42.0

3 years ago

0.39.1

3 years ago

0.39.0

3 years ago

0.35.0

3 years ago

0.31.2

3 years ago

0.39.3

3 years ago

0.39.2

3 years ago

0.31.1

3 years ago

0.31.0

3 years ago

0.47.1

3 years ago

0.47.2

3 years ago

0.47.0

3 years ago

0.43.1

3 years ago

0.43.2

3 years ago

0.29.0

3 years ago

0.27.3

3 years ago

0.27.4-0

3 years ago

0.28.1

3 years ago

0.28.0

3 years ago

0.27.2

3 years ago

0.27.1

4 years ago

0.27.0

4 years ago

0.20.1

4 years ago

0.20.0

4 years ago

0.19.0

4 years ago

0.11.0

4 years ago

0.11.1

4 years ago

0.13.0

4 years ago

0.11.2

4 years ago

0.11.3

4 years ago

0.15.0

4 years ago

0.15.1

4 years ago

0.17.0

4 years ago

0.25.4

4 years ago

0.25.0-0

4 years ago

0.25.3

4 years ago

0.25.0-1

4 years ago

0.25.2

4 years ago

0.3.0

4 years ago

0.25.1

4 years ago

0.25.0

4 years ago

0.21.4

4 years ago

0.23.1

4 years ago

0.21.3

4 years ago

0.23.0

4 years ago

0.21.2

4 years ago

0.21.1

4 years ago

0.9.0

4 years ago

0.7.1

4 years ago

0.9.1

4 years ago

0.5.0

4 years ago

0.7.0

4 years ago

0.21.0

4 years ago

0.18.1

4 years ago

0.18.2

4 years ago

0.10.1

4 years ago

0.12.0

4 years ago

0.10.2

4 years ago

0.12.1

4 years ago

0.10.3

4 years ago

0.14.0

4 years ago

0.12.2

4 years ago

0.10.4

4 years ago

0.16.0

4 years ago

0.16.1

4 years ago

0.18.0

4 years ago

0.16.2

4 years ago

0.10.0

4 years ago

0.26.0

4 years ago

0.24.2

4 years ago

0.24.1

4 years ago

0.24.0

4 years ago

0.20.4

4 years ago

0.20.3

4 years ago

0.22.0

4 years ago

0.20.2

4 years ago

0.8.0

4 years ago

0.25.5-0

4 years ago

0.4.0

4 years ago

0.6.0

4 years ago

0.2.1

4 years ago

0.2.0

4 years ago

0.2.3

4 years ago

0.2.2

4 years ago

0.1.0

4 years ago