0.2.0 • Published 4 years ago

@parli/sdk v0.2.0

Weekly downloads
-
License
-
Repository
github
Last release
4 years ago

Lustre API

This exposes the Lustre API as a series of React hooks in a type-safe way. It will automatically account for routing and request batching, and users of this SDK should avoid trying to manually optimize requests. If anything appears not optimal, please file a bug rather than attempting to work around it.

API and Versioning

This package follows semantic versioning practices.

Anything not exported from the root-level package IS NOT considered part of the public API, and may be unstable. Attempting to "reach in" deeper to the package is not supported in any way, and has no guarantees about following SemVer.

Additionally, the type field on identifiers is considered a private implementation detail and is also not covered by SemVer. See the section on identifers below.

Required Set-up

In order to set up the necessary React Context, the Provider must be registered:

// index.tsx or somewhere else near the package root
import React from 'react'
import ReactDOM from 'react-dom'
import { ApiProvider } from '@parli/sdk' // Add this
import App from './App'

// Replace this
// ReactDOM.render(<App />, document.getElementById('root'))
// With this:
ReactDOM.render(<ApiProvider><App /></ApiProvider>, document.getElementById('root'))

The API hooks WILL NOT FUNCTION without this provider registered into the rendering tree.

Additionally, an API key SHOULD be set for applications that must use one:

import { setApiKey } from '@parli/sdk'
setApiKey('your-access-token')

Usage

Important: Any function in the package starting with use is a React Hook, and its usage is strictly required to follow the Rules of Hooks (RoH). As they are the primary interaction with this package, developers should be familiar with the RoH and are strongly encouraged to set up the RoH linters.

In general, avoid trying to be clever about request management or other batching. This library will optimize request handling, and if you find yourself trying to outsmart it, it's probably a bug - please file one!

Queries

import { queries } from '@parli/sdk'

All of the functions in this structure correspond to the various Queries in the API. They are all type-safe, and parameterized in a way to avoid type juggling. Queries will be routed automatically to the correct back-end service, and batched appropriately.

The names do not necessarily correspond 1:1 with the API names, especially for "either-or" queries (e.g. graph_search accepts question or context but not both, so two methods will be exposed to handle those cases)

The queries functions return the body to be passed to the useQuery hook, not the actual response. The formatted outbound request is not intended for use in any other place. See its documentation below.

Hooks

useEntity

Takes an entity identifer and returns the entity, or undefined if the entity has not been loaded yet. A request to load the entity will automatically run.

Generally, the identifer will be the return type of something else - either a query response or the property of some other entity.

useEntities

Takes a list of entity identifiers and returns a list of loaded entities. Any entities not yet loaded will be requested. For convenience with the mechanics of useQuery's not loaded state, this method also accepts undefined.

Note: If multiple entity Id types are passed (e.g. a Brand Id and a Spec Id), the return type will infer that the entities can be any of those corresponding entities (e.g. Array<Entities.Brand | Entities.Spec>). In most circumstances, this is an anti-pattern and should be avoided.

useQuery

Takes a typed Query (i.e. the return value from one of the queries functions) and returns the response from the API. This will deal with the client hashes via the input parameters, so you don't need to think about that.

Identifiers

Entities and many queries work with identifers. Due to limitations of Javascript (and therefore typescript), type information of identifers needs to be manually propagated - this is done as a tiny object of { id: string, type: string }. Day to day, this can be mostly ignored, as the hooks accept this structure and know what to do with it.

You SHOULD use identifers as React component props, and pass them around as a whole object:

import React from 'react'
import { Entities } from '@parli/sdk'

const ParentComponent: React.FC = () => {
  const brandId = ... // query result, field from property, etc
  return (
    <ChildComponent brandId={brandId} />
  )
}

interface ChildProps {
  brandId: Entities.Brand['id']
}
const ChildComponent: React.FC<ChildProps> = ({ brandId }) => {
  // const brand = useEntity(brandId)
  // ...
}

However, when dealing with lists and keys, it will be necessary to interact with the internals:

// in a React FC
const entities: Entities.Brand[] = [] // e.g. result of a query or useEntities
return (
  <ul>
    {entities.map(brand => <li key={brand.id.id}>{brand.name}</li>)}
  </ul>
)

If you find yourself inspecting the contents of the Id structure anywhere else, you are probably doing something wrong.

Examples

import React from 'react'

import {
  Entities,
  queries,
  useEntities,
  useEntity,
  useQuery,
} from '@parli/sdk'

const MyComponent: React.FC = () => {
  const familyIds = useQuery(queries.uncategorizedFamiliesQueue())
  const families = useEntities(familyIds)

  return (
    <ul>
      {families.map(fam => <li key={fam.id.id}>{fam.name}</li>)}
    </ul>
  )
}

export default MyComponent

Types

The type information for Entities is explicitly exported, for the common use-case of adding type annotations to a component.

import React from 'react'
import { Entities } from '@parli/sdk'

interface Props {
  brandId: Entities.Brand['id']
}
const MyComponent: React.FC<Props> = ({ brandId }) => {
  // ...
}

At this time, query responses are not directly exported for similar use. However, type information will still be attached to the return value of useQuery.

Known issues

Bugs

  • Reducers don't directly tie to state tree, resulting in potential synchroniztion issues
    • e.g. before fmly entity reducer is added, useEntity(famId) is a hard crash

Missing functionality

  • Most entities are missing
  • Most queries are missing
  • Attributes are not supported yet
  • Mutations are not supported yet