Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(js-api-clients): move js-api-clients to the opentrons repo #8515

Merged
merged 21 commits into from
Oct 14, 2021
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions .github/workflows/react-api-client-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Run tests, build components bundle, and deploy it to sandbox

name: 'JS API Clients test'

on:
pull_request:
paths:
- 'react-api-client/**'
- 'api-client/**'
- 'package.json'
- '.github/workflows/react-api-client-test.yaml'
push:
paths:
- 'react-api-client/**'
- 'api-client/**'
- 'package.json'
- '.github/workflows/react-api-client-test.yaml'
branches:
- '*'
workflow_dispatch:

defaults:
run:
shell: bash

env:
CI: true

jobs:
js-unit-test:
name: 'react-api-client unit tests'
timeout-minutes: 30
runs-on: 'ubuntu-18.04'
steps:
- uses: 'actions/checkout@v2'
- uses: 'actions/setup-node@v1'
with:
node-version: '14'
- name: 'install libudev for usb-detection'
run: sudo apt-get update && sudo apt-get install libudev-dev
- name: 'cache yarn cache'
uses: actions/cache@v2
with:
path: |
${{ github.workspace }}/.yarn-cache
${{ github.workspace }}/.npm-cache
key: js-${{ secrets.GH_CACHE_VERSION }}-${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
js-${{ secrets.GH_CACHE_VERSION }}-${{ runner.os }}-yarn-
- name: 'setup-js'
run: |
npm config set cache ./.npm-cache
yarn config set cache-folder ./.yarn-cache
make setup-js
- name: 'run react-api-client unit tests'
run: |
yarn jest --coverage=true --ci=true --collectCoverageFrom="react-api-client/src/**/*.(js|ts|tsx)" react-api-client/src
- name: 'Upload coverage report'
uses: codecov/codecov-action@v2
with:
files: ./coverage/lcov.info
flags: react-api-client
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,7 @@ shared-data/python/pyproject.toml

# Static storybook build artifacts
storybook-static/

# api client type caches
api-client/lib
react-api-client/lib
19 changes: 19 additions & 0 deletions api-client/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# opentrons api-client makefile

# using bash instead of /bin/bash in SHELL prevents macOS optimizing away our PATH update
# TODO(mc, 2021-02-12): this may be unnecessary by using `yarn run` instead
SHELL := bash

# standard targets
#####################################################################

.PHONY: all
all: clean build

.PHONY: clean
clean:
tsc --build --clean && yarn shx rm -rf \"dist\"

.PHONY: build
build:
rollup --config rollup.config.js
31 changes: 31 additions & 0 deletions api-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Opentrons HTTP API Client

Opentrons robot HTTP API client for Node.js and browsers. Compatible with [Opentrons robot software][] `v4` and later.

[opentrons robot software]: https://github.com/Opentrons/opentrons

## Getting Started

### Installation

```shell
npm install @opentrons/api-client
```

### Usage

```typescript
import { HostConfig, Response, Health, getHealth } from '@opentrons/api-client'

const host: HostConfig = { hostname: 'OT2CEP9999999A99.local' }

getHealth(host)
.then((response: Response<Health>) => console.log(response.data))
.catch(error => console.error(error))
```

## Details

The `@opentrons/api-client` module is built using [axios][].

[axios]: https://github.com/axios/axios
18 changes: 18 additions & 0 deletions api-client/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"private": true,
"name": "@opentrons/api-client",
"description": "Opentrons robot API client for Node.js and the browser",
"version": "0.0.0",
"license": "Apache-2.0",
"main": "dist/api-client.js",
"module": "dist/api-client.mjs",
"types": "lib/index.d.ts",
"source": "src/index.ts",
"browser": {
"./dist/api-client.js": "./dist/api-client.browser.js",
"./dist/api-client.mjs": "./dist/api-client.browser.mjs"
},
"dependencies": {
"axios": "^0.21.1"
}
}
9 changes: 9 additions & 0 deletions api-client/src/health/getHealth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { GET, request } from '../request'

import type { ResponsePromise } from '../request'
import type { HostConfig } from '../types'
import type { Health } from './types'

export function getHealth(config: HostConfig): ResponsePromise<Health> {
return request<Health>(GET, '/health', null, config)
}
2 changes: 2 additions & 0 deletions api-client/src/health/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { getHealth } from './getHealth'
export type { Health, HealthLinks } from './types'
19 changes: 19 additions & 0 deletions api-client/src/health/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export interface Health {
name: string
api_version: string
fw_version: string
board_revision: string
logs: string[]
system_version: string
maximum_protocol_api_version: [major: number, minor: number]
minimum_protocol_api_version: [major: number, minor: number]
links: HealthLinks
}

export interface HealthLinks {
apiLog: string
serialLog: string
serverLog: string
apiSpec: string
systemTime: string
}
5 changes: 5 additions & 0 deletions api-client/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// api client entry point
export type { HostConfig } from './types'
export * from './request'
export * from './health'
export * from './sessions'
32 changes: 32 additions & 0 deletions api-client/src/request.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import axios, { AxiosRequestConfig } from 'axios'

import type { Method, AxiosPromise, AxiosResponse } from 'axios'
import type { HostConfig } from './types'

export type ResponsePromise<Data> = AxiosPromise<Data>

export type Response<Data> = AxiosResponse<Data>

export const DEFAULT_PORT = 31950

export const DEFAULT_HEADERS = {
'Opentrons-Version': '*',
}

export const GET = 'GET'
export const POST = 'POST'
export const DELETE = 'DELETE'

export function request<ResData, ReqData = null>(
method: Method,
url: string,
data: ReqData,
config: HostConfig,
params?: AxiosRequestConfig['params']
): ResponsePromise<ResData> {
const { hostname, port } = config
const headers = { ...DEFAULT_HEADERS }
const baseURL = `http:https://${hostname}:${port ?? DEFAULT_PORT}`

return axios.request({ headers, method, baseURL, url, data, params })
}
21 changes: 21 additions & 0 deletions api-client/src/sessions/createSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { POST, request } from '../request'

import type { ResponsePromise } from '../request'
import type { HostConfig } from '../types'
import type { Session } from './types'
import { SessionType } from '.'

export interface CreateSessionData {
sessionType: SessionType
createParams?: Record<string, unknown>
}

export function createSession(
config: HostConfig,
data?: CreateSessionData
): ResponsePromise<Session> {
return request<
Session,
{ data: { sessionType: SessionType; createParams?: unknown } | undefined }
>(POST, '/sessions', { data }, config)
}
12 changes: 12 additions & 0 deletions api-client/src/sessions/deleteSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { DELETE, request } from '../request'

import type { ResponsePromise } from '../request'
import type { HostConfig } from '../types'
import type { Session } from './types'

export function deleteSession(
config: HostConfig,
sessionId: string
): ResponsePromise<Session> {
return request<Session>(DELETE, `/sessions/${sessionId}`, null, config)
}
12 changes: 12 additions & 0 deletions api-client/src/sessions/getSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { GET, request } from '../request'

import type { ResponsePromise } from '../request'
import type { HostConfig } from '../types'
import type { Session } from './types'

export function getSession(
config: HostConfig,
sessionId: string
): ResponsePromise<Session> {
return request<Session>(GET, `/sessions/${sessionId}`, null, config)
}
12 changes: 12 additions & 0 deletions api-client/src/sessions/getSessions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { GET, request } from '../request'

import type { ResponsePromise } from '../request'
import type { HostConfig } from '../types'
import type { Sessions, SessionType } from './types'

export function getSessions(
config: HostConfig,
params?: { session_type: SessionType }
): ResponsePromise<Sessions> {
return request<Sessions>(GET, `/sessions`, null, config, params)
}
7 changes: 7 additions & 0 deletions api-client/src/sessions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export { getSession } from './getSession'
export { deleteSession } from './deleteSession'
export { createSession } from './createSession'
export { getSessions } from './getSessions'

export * from './types'
export type { CreateSessionData } from './createSession'
71 changes: 71 additions & 0 deletions api-client/src/sessions/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
export const SESSION_TYPE_CALIBRATION_HEALTH_CHECK: 'calibrationCheck' =
'calibrationCheck'
export const SESSION_TYPE_TIP_LENGTH_CALIBRATION: 'tipLengthCalibration' =
'tipLengthCalibration'
export const SESSION_TYPE_DECK_CALIBRATION: 'deckCalibration' =
'deckCalibration'
export const SESSION_TYPE_PIPETTE_OFFSET_CALIBRATION: 'pipetteOffsetCalibration' =
'pipetteOffsetCalibration'

export const SESSION_TYPE_BASIC: 'basic' = 'basic'

export type SessionType =
| typeof SESSION_TYPE_CALIBRATION_HEALTH_CHECK
| typeof SESSION_TYPE_TIP_LENGTH_CALIBRATION
| typeof SESSION_TYPE_DECK_CALIBRATION
| typeof SESSION_TYPE_PIPETTE_OFFSET_CALIBRATION
| typeof SESSION_TYPE_BASIC

interface CalibrationCheckSession {
id: string
sessionType: typeof SESSION_TYPE_CALIBRATION_HEALTH_CHECK
createParams: Record<string, unknown>
}

interface TipLengthCalibrationSession {
id: string
sessionType: typeof SESSION_TYPE_TIP_LENGTH_CALIBRATION
createParams: Record<string, unknown>
}

interface DeckCalibrationSession {
id: string
sessionType: typeof SESSION_TYPE_DECK_CALIBRATION
createParams: {}
}

interface PipetteOffsetCalibrationSession {
id: string
sessionType: typeof SESSION_TYPE_PIPETTE_OFFSET_CALIBRATION
createParams: Record<string, unknown>
}

interface BasicSession {
id: string
sessionType: typeof SESSION_TYPE_BASIC
createParams: Record<string, unknown>
}

export type SessionData =
| CalibrationCheckSession
| TipLengthCalibrationSession
| DeckCalibrationSession
| PipetteOffsetCalibrationSession
| BasicSession

interface ResourceLink {
href: string
meta?: Partial<{ [key: string]: string | null | undefined }>
}

type ResourceLinks = Record<string, ResourceLink | string | null | undefined>

export interface Session {
data: SessionData
links?: ResourceLinks
}

export interface Sessions {
data: SessionData[]
links?: ResourceLinks
}
4 changes: 4 additions & 0 deletions api-client/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface HostConfig {
hostname: string
port?: number | null
}
10 changes: 10 additions & 0 deletions api-client/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "../tsconfig-base.json",
"references": [],
"compilerOptions": {
"composite": true,
"rootDir": "src",
"outDir": "lib"
},
"include": ["src"]
}
10 changes: 9 additions & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ module.exports = {
'^@opentrons/components$': `@opentrons/components/src/index.ts`,
'^@opentrons/shared-data$': `@opentrons/shared-data/js/index.ts`,
'^@opentrons/step-generation$': `@opentrons/step-generation/src/index.ts`,
'^@opentrons/api-client$': `@opentrons/api-client/src/index.ts`,
'^@opentrons/react-api-client$': `@opentrons/react-api-client/src/index.ts`,
},
},
],
Expand All @@ -58,7 +60,13 @@ module.exports = {
// apps that should be polyfilled
// these projects require `core-js` in their package.json `dependencies`
{
test: ['app/**/*', 'labware-library/**/*', 'protocol-designer/**/*'],
test: [
'app/**/*',
'labware-library/**/*',
'protocol-designer/**/*',
'react-api-client/**/*',
'api-client/**/*',
],
presets: [['@babel/preset-env', { useBuiltIns: 'usage', corejs: 3 }]],
},
],
Expand Down
Loading