# Vetted SDK

The Vetted SDK provides utility methods for accessing and parsing the requests from the [Vetted API](./tree/main/src/schema/README.md). It provides fetch promises, and exposes the API schema for type safe use in other projects.

Under the hood it also does automatic query request batching and client side storage for resolved queries so you should not have to worry about optimizing any of those things yourself.

## API and Versioning

This package api exports follows semantic versioning practices.

Anything not exported from the root-level package is NOT considered part of the public module API, and may be unstable and break without respecting semver.

## Schema

This package defines and acts as the source of truth for the Vetted API schema. Everything defined within `/schema` is for defining types only. They are all serializable to JSON and should not have any actual code within it.

### `Queries`

A dictionary of [query](./tree/main/src/schema#queries) type definitions to use for typing Vetted API compatible variable instances. Query types are used for creating query objects to pass to query fetcher functions and to ensure your interface instances conform to the Vetted API spec.

Query interfaces are always JSON objects.

### `Responses`

A dictionary of [response](./tree/main/src/schema#query-responses) type definitions to use for typing Vetted API compatible variable instances. Response types are used for accessing properties of Vetted API query responses returned by the fetcher functions and to ensure your interface instances conform to the Vetted API spec.

### `ServerError`

An [error](./tree/main/src/schema#error-handling) interface that may be thrown by a fetcher when a Vetted API request fails.

#### `HttpError`

`HttpError`s are a type of `ServerError` that are returned by an API server to indicate what kind of network failure occurred. This is the primary type of error you will encounter that may be thrown by a fetcher.

#### `FutureError`

`FutureError`s are a fallback error type to represent any `ServerError` that may be implemented that the SDK has not been updated to support yet. If you encounter an error that parses to a `FutureError` it likely indicates that you need to update your SDK package.

### `Api`

The interface that defines the full network request and response JSON body structure of the Vetted API. This is intended for use by resolver servers to be able to implement responders for client network requests and should NOT be used by clients.

The `Api` export has all the top level fields set to optional as individual bodies will only be requesting a subset of the API.

#### `ApiQueries`

Defines the interface structure for the `queries` portion of the Vetted API http JSON body. Exposes all currently implemented and requestable queries.

#### `ApiResponses`

Defines the interface structure for the `responses` portion of the Vetted API http JSON body. Exposes all currently implemented and requestable responses.

#### `ApiErrors`

Defines the interface structure for the `errors` portion of the Vetted API http JSON body. Exposes errors for all currently implemented and requestable queries.

## Api

Api exports are for functions and classes that actually handle executing network requests.

### `fetchQuery`

Requests a query from an API server and returns a promise that may resolve as the query response or reject with a `QueryError`

### `QueryResolver`

A query manager for batching together queries into one request and constructing query request objects and executing an HTTP request for network retrieval as well as fulfilling promises resolving those queries

Instances of this class may be passed to query fetcher functions and hooks to customize the query resolver used to execute the query. Direct use should NOT be done by clients and clients should only pass them to request functions and hooks.

#### Changing the default `QueryResolver`

**WARNING**: Changing the default query resolver is not guaranteed to be safe and may cause queries to be routed to the wrong server, including potentially routing a user's request to a different user if they are swapped in the middle of app execution. The helper functions are currently considered unstable until a better approach is decided on and will change in some point in the future.

Getter and setter functions `_getDefaultQueryResolver` and `_setDefaultQueryResolver` are exposed to change and customize the default query resolver that gets used when a query resolver is not passed in to a query queing method. These should be only used in initialization before any requests are made, otherwise queries may be routed to the wrong server or with incorrect credentials.

## Error Handling

Fetch functions may throw error objects that extend the class `QueryError`. These errors can be caught from the returned promise or with a `try` `catch` block. To distinguish between error types and narrow their type signatures you can do `if (error instanceof QueryError) {}` to check which kind of QueryError an error is so you can safely access their properties and decide how to handle the error.

### `QueryError`

Base error type for errors related to query errors

### `QueryFetchError`

Query error for errors related to a query fetch call failing

### `QueryReferenceError`

Query error for errors related to a query response object missing an expected reference

### `QueryResponseError`

Query error for errors related to a query response object returning an error object

### `QueryHttpError`

Query error for errors related to a query fetch response returning an http error


## Development

- check out the code
- install dependencies by running `yarn`

### Using a development version in an application

If you would like to update the SDK locally and test those changes without having to publish a new dev version of the package you can link the SDK to your project using `yarn link`.

In *this library's root*:

1. Install dependencies by running `yarn`
2. Run `yarn link` in the root of the SDK, which will allow it to be locally linked by other projects

In *your application root*:

3. *Recommended*: clean-install your appliation's dependencies, by running `rm -rf node_modules` and then `yarn` in your application's root
4. Run `yarn link @lustre/sdk`, which tells your application to use the shared local copy of this SDK

Changes made in this repository will need to be manually built with `yarn build`; if you are using `yarn watch` in your application (like the default Create-React-App provides), it should pick up on the fresh library build and do its own build.

### Using a development version in a Next.js application (_may only be relevant if a custom webpack config is used_)

Next works a bit differently so in order to get local version of the SDK linked slightly different steps are required.

In *this library's root*:

1. Install dependencies, if you have not already, with `yarn`
2. Run `yarn link` in the root of the SDK, which will allow it to be locally linked by other projects

In *your Next.js application root*:

3. *Recommended*: clean-install your appliation's dependencies, by running `rm -rf node_modules` and then `yarn` in your application's root
4. Run `yarn link @lustre/sdk`, which tells your application to use the shared local copy of this SDK
5. In the app's `next.config.js` file add this snippet in the relevant places:
```js
const path = require("path")

module.exports = {
  webpack(config) {
    config.resolve.alias = {
      ...config.resolve.alias,
      react: path.resolve("./node_modules/react"),
      "@types/react": path.resolve("./node_modules/@types/react"),
    }
  }
}
```

## Version release process

This package follows [semantic versioning](https://semver.org/) practices.

New version release is done by publishing to the [npm registry](https://www.npmjs.com/package/@lustre/sdk). In order to publish you have to first make sure you're listed as a maintainer.

If you're not already familiar with how to publish to npm, the simplest way to go through the release process is by using [`np`](https://github.com/sindresorhus/np).
It can be installed either globally (as suggested in their docs) or used via `npx`.

### Steps when using `np`:
- Make sure you're logged in to `npm` locally in your terminal (`npm login`)
- Make sure you're on the `master` branch and up to date, including tags (`git fetch --all --tags`).
- Run `np` (via `npx` - `npx np`)
- Fix any pre-release issues that pop up (common ones: tests failing, existing local changes, etc..)
- If prompted about "new" files not being a part of the release and you're not sure what to do then you probably need to confirm 😄 (hit Y since the default is No).
- Select the appropriate type of version bump (patch, minor, major).
- If everything worked a browser window will pop up where you can edit the release change log.
- You're done!
