diff options
author | Kirill Rogovoy <[email protected]> | 2021-07-23 11:02:26 +0300 |
---|---|---|
committer | Kirill Rogovoy <[email protected]> | 2021-07-23 11:02:26 +0300 |
commit | 73308af061af5e17ac7d4a73fa027a2f303c70dd (patch) | |
tree | 816fb8231e13f58f7afe822742513b3150cdc871 /app_expo/services | |
parent | b8c58914cc1e251ce161905340647b6824d0a7c4 (diff) |
Update graph data when Emacs node changes + minor improvements
Diffstat (limited to 'app_expo/services')
-rw-r--r-- | app_expo/services/api/api-config.ts | 27 | ||||
-rw-r--r-- | app_expo/services/api/api-problem.test.ts | 100 | ||||
-rw-r--r-- | app_expo/services/api/api-problem.ts | 74 | ||||
-rw-r--r-- | app_expo/services/api/api.ts | 102 | ||||
-rw-r--r-- | app_expo/services/api/api.types.ts | 13 | ||||
-rw-r--r-- | app_expo/services/api/character-api.ts | 37 | ||||
-rw-r--r-- | app_expo/services/api/index.ts | 2 | ||||
-rw-r--r-- | app_expo/services/reactotron/index.ts | 1 | ||||
-rw-r--r-- | app_expo/services/reactotron/reactotron-config.ts | 30 | ||||
-rw-r--r-- | app_expo/services/reactotron/reactotron.ts | 185 | ||||
-rw-r--r-- | app_expo/services/reactotron/tron.ts | 2 | ||||
-rw-r--r-- | app_expo/services/reactotron/tron.web.ts | 2 |
12 files changed, 0 insertions, 575 deletions
diff --git a/app_expo/services/api/api-config.ts b/app_expo/services/api/api-config.ts deleted file mode 100644 index b939c0e..0000000 --- a/app_expo/services/api/api-config.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Use this import if you want to use "env.js" file -// const { API_URL } = require("../../config/env") -// Or just specify it directly like this: -const API_URL = 'http://example.com' - -/** - * The options used to configure the API. - */ -export interface ApiConfig { - /** - * The URL of the api. - */ - url: string - - /** - * Milliseconds before we timeout the request. - */ - timeout: number -} - -/** - * The default configuration for the app. - */ -export const DEFAULT_API_CONFIG: ApiConfig = { - url: API_URL || 'https://jsonplaceholder.typicode.com', - timeout: 10000, -} diff --git a/app_expo/services/api/api-problem.test.ts b/app_expo/services/api/api-problem.test.ts deleted file mode 100644 index f8b4041..0000000 --- a/app_expo/services/api/api-problem.test.ts +++ /dev/null @@ -1,100 +0,0 @@ -import { getGeneralApiProblem } from './api-problem' -import { ApiErrorResponse } from 'apisauce' - -test('handles connection errors', () => { - expect( - getGeneralApiProblem({ - problem: 'CONNECTION_ERROR', - } as ApiErrorResponse<null>), - ).toEqual({ - kind: 'cannot-connect', - temporary: true, - }) -}) - -test('handles network errors', () => { - expect( - getGeneralApiProblem({ - problem: 'NETWORK_ERROR', - } as ApiErrorResponse<null>), - ).toEqual({ - kind: 'cannot-connect', - temporary: true, - }) -}) - -test('handles timeouts', () => { - expect( - getGeneralApiProblem({ - problem: 'TIMEOUT_ERROR', - } as ApiErrorResponse<null>), - ).toEqual({ - kind: 'timeout', - temporary: true, - }) -}) - -test('handles server errors', () => { - expect(getGeneralApiProblem({ problem: 'SERVER_ERROR' } as ApiErrorResponse<null>)).toEqual({ - kind: 'server', - }) -}) - -test('handles unknown errors', () => { - expect( - getGeneralApiProblem({ - problem: 'UNKNOWN_ERROR', - } as ApiErrorResponse<null>), - ).toEqual({ - kind: 'unknown', - temporary: true, - }) -}) - -test('handles unauthorized errors', () => { - expect( - getGeneralApiProblem({ - problem: 'CLIENT_ERROR', - status: 401, - } as ApiErrorResponse<null>), - ).toEqual({ - kind: 'unauthorized', - }) -}) - -test('handles forbidden errors', () => { - expect( - getGeneralApiProblem({ - problem: 'CLIENT_ERROR', - status: 403, - } as ApiErrorResponse<null>), - ).toEqual({ - kind: 'forbidden', - }) -}) - -test('handles not-found errors', () => { - expect( - getGeneralApiProblem({ - problem: 'CLIENT_ERROR', - status: 404, - } as ApiErrorResponse<null>), - ).toEqual({ - kind: 'not-found', - }) -}) - -test('handles other client errors', () => { - expect( - getGeneralApiProblem({ - problem: 'CLIENT_ERROR', - status: 418, - } as ApiErrorResponse<null>), - ).toEqual({ - kind: 'rejected', - }) -}) - -test('handles cancellation errors', () => { - expect(getGeneralApiProblem({ problem: 'CANCEL_ERROR' } as ApiErrorResponse<null>)).toBeNull() -}) diff --git a/app_expo/services/api/api-problem.ts b/app_expo/services/api/api-problem.ts deleted file mode 100644 index 15ca850..0000000 --- a/app_expo/services/api/api-problem.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { ApiResponse } from 'apisauce' - -export type GeneralApiProblem = - /** - * Times up. - */ - | { kind: 'timeout'; temporary: true } - /** - * Cannot connect to the server for some reason. - */ - | { kind: 'cannot-connect'; temporary: true } - /** - * The server experienced a problem. Any 5xx error. - */ - | { kind: 'server' } - /** - * We're not allowed because we haven't identified ourself. This is 401. - */ - | { kind: 'unauthorized' } - /** - * We don't have access to perform that request. This is 403. - */ - | { kind: 'forbidden' } - /** - * Unable to find that resource. This is a 404. - */ - | { kind: 'not-found' } - /** - * All other 4xx series errors. - */ - | { kind: 'rejected' } - /** - * Something truly unexpected happened. Most likely can try again. This is a catch all. - */ - | { kind: 'unknown'; temporary: true } - /** - * The data we received is not in the expected format. - */ - | { kind: 'bad-data' } - -/** - * Attempts to get a common cause of problems from an api response. - * - * @param response The api response. - */ -export function getGeneralApiProblem(response: ApiResponse<any>): GeneralApiProblem | void { - switch (response.problem) { - case 'CONNECTION_ERROR': - return { kind: 'cannot-connect', temporary: true } - case 'NETWORK_ERROR': - return { kind: 'cannot-connect', temporary: true } - case 'TIMEOUT_ERROR': - return { kind: 'timeout', temporary: true } - case 'SERVER_ERROR': - return { kind: 'server' } - case 'UNKNOWN_ERROR': - return { kind: 'unknown', temporary: true } - case 'CLIENT_ERROR': - switch (response.status) { - case 401: - return { kind: 'unauthorized' } - case 403: - return { kind: 'forbidden' } - case 404: - return { kind: 'not-found' } - default: - return { kind: 'rejected' } - } - case 'CANCEL_ERROR': - return null - } - - return null -} diff --git a/app_expo/services/api/api.ts b/app_expo/services/api/api.ts deleted file mode 100644 index 4093d34..0000000 --- a/app_expo/services/api/api.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { ApisauceInstance, create, ApiResponse } from 'apisauce' -import { getGeneralApiProblem } from './api-problem' -import { ApiConfig, DEFAULT_API_CONFIG } from './api-config' -import * as Types from './api.types' - -/** - * Manages all requests to the API. - */ -export class Api { - /** - * The underlying apisauce instance which performs the requests. - */ - apisauce: ApisauceInstance - - /** - * Configurable options. - */ - config: ApiConfig - - /** - * Creates the api. - * - * @param config The configuration to use. - */ - constructor(config: ApiConfig = DEFAULT_API_CONFIG) { - this.config = config - } - - /** - * Sets up the API. This will be called during the bootup - * sequence and will happen before the first React component - * is mounted. - * - * Be as quick as possible in here. - */ - setup() { - // construct the apisauce instance - this.apisauce = create({ - baseURL: this.config.url, - timeout: this.config.timeout, - headers: { - Accept: 'application/json', - }, - }) - } - - /** - * Gets a list of users. - */ - async getUsers(): Promise<Types.GetUsersResult> { - // make the api call - const response: ApiResponse<any> = await this.apisauce.get(`/users`) - - // the typical ways to die when calling an api - if (!response.ok) { - const problem = getGeneralApiProblem(response) - if (problem) return problem - } - - const convertUser = (raw) => { - return { - id: raw.id, - name: raw.name, - } - } - - // transform the data into the format we are expecting - try { - const rawUsers = response.data - const resultUsers: Types.User[] = rawUsers.map(convertUser) - return { kind: 'ok', users: resultUsers } - } catch { - return { kind: 'bad-data' } - } - } - - /** - * Gets a single user by ID - */ - - async getUser(id: string): Promise<Types.GetUserResult> { - // make the api call - const response: ApiResponse<any> = await this.apisauce.get(`/users/${id}`) - - // the typical ways to die when calling an api - if (!response.ok) { - const problem = getGeneralApiProblem(response) - if (problem) return problem - } - - // transform the data into the format we are expecting - try { - const resultUser: Types.User = { - id: response.data.id, - name: response.data.name, - } - return { kind: 'ok', user: resultUser } - } catch { - return { kind: 'bad-data' } - } - } -} diff --git a/app_expo/services/api/api.types.ts b/app_expo/services/api/api.types.ts deleted file mode 100644 index 21d3c87..0000000 --- a/app_expo/services/api/api.types.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { GeneralApiProblem } from './api-problem' -import { Character } from '../../models/character/character' - -export interface User { - id: number - name: string -} - -export type GetUsersResult = { kind: 'ok'; users: User[] } | GeneralApiProblem -export type GetUserResult = { kind: 'ok'; user: User } | GeneralApiProblem - -export type GetCharactersResult = { kind: 'ok'; characters: Character[] } | GeneralApiProblem -export type GetCharacterResult = { kind: 'ok'; character: Character } | GeneralApiProblem diff --git a/app_expo/services/api/character-api.ts b/app_expo/services/api/character-api.ts deleted file mode 100644 index e28ec48..0000000 --- a/app_expo/services/api/character-api.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { ApiResponse } from 'apisauce' -import { Api } from './api' -import { GetCharactersResult } from './api.types' -import { getGeneralApiProblem } from './api-problem' - -const API_PAGE_SIZE = 50 - -export class CharacterApi { - private api: Api - - constructor(api: Api) { - this.api = api - } - - async getCharacters(): Promise<GetCharactersResult> { - try { - // make the api call - const response: ApiResponse<any> = await this.api.apisauce.get( - 'https://raw.githubusercontent.com/infinitered/ignite/master/data/rick-and-morty.json', - { amount: API_PAGE_SIZE }, - ) - - // the typical ways to die when calling an api - if (!response.ok) { - const problem = getGeneralApiProblem(response) - if (problem) return problem - } - - const characters = response.data.results - - return { kind: 'ok', characters } - } catch (e) { - __DEV__ && console.tron.log(e.message) - return { kind: 'bad-data' } - } - } -} diff --git a/app_expo/services/api/index.ts b/app_expo/services/api/index.ts deleted file mode 100644 index f133e64..0000000 --- a/app_expo/services/api/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './api' -export * from './api.types' diff --git a/app_expo/services/reactotron/index.ts b/app_expo/services/reactotron/index.ts deleted file mode 100644 index 0c02f1f..0000000 --- a/app_expo/services/reactotron/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './reactotron' diff --git a/app_expo/services/reactotron/reactotron-config.ts b/app_expo/services/reactotron/reactotron-config.ts deleted file mode 100644 index 40e9c93..0000000 --- a/app_expo/services/reactotron/reactotron-config.ts +++ /dev/null @@ -1,30 +0,0 @@ -export interface ReactotronConfig { - /** The name of the app. */ - name?: string - /** The host to connect to: default 'localhost'. */ - host?: string - /** Should we use async storage */ - useAsyncStorage?: boolean - /** Should we clear Reactotron when load? */ - clearOnLoad?: boolean - /** Root state logging. */ - state?: { - /** log the initial data that we put into the state on startup? */ - initial?: boolean - /** log snapshot changes. */ - snapshots?: boolean - } -} - -/** - * The default Reactotron configuration. - */ -export const DEFAULT_REACTOTRON_CONFIG: ReactotronConfig = { - clearOnLoad: true, - host: 'localhost', - useAsyncStorage: true, - state: { - initial: true, - snapshots: false, - }, -} diff --git a/app_expo/services/reactotron/reactotron.ts b/app_expo/services/reactotron/reactotron.ts deleted file mode 100644 index 6a20a75..0000000 --- a/app_expo/services/reactotron/reactotron.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { Tron } from './tron' -import AsyncStorage from '@react-native-async-storage/async-storage' -import { RootStore } from '../../models/root-store/root-store' -import { onSnapshot } from 'mobx-state-tree' -import { ReactotronConfig, DEFAULT_REACTOTRON_CONFIG } from './reactotron-config' -import { mst } from 'reactotron-mst' -import { clear } from '../../utils/storage' -import { RootNavigation } from '../../navigators' -import { Platform } from 'react-native' - -// Teach TypeScript about the bad things we want to do. -declare global { - interface Console { - /** - * Hey, it's Reactotron if we're in dev, and no-ops if we're in prod. - */ - tron: typeof Tron - } -} - -/** Do Nothing. */ -const noop = () => undefined - -// in dev, we attach Reactotron, in prod we attach a interface-compatible mock. -if (__DEV__) { - console.tron = Tron // attach reactotron to `console.tron` -} else { - // attach a mock so if things sneaky by our __DEV__ guards, we won't crash. - console.tron = { - benchmark: noop, - clear: noop, - close: noop, - configure: noop, - connect: noop, - display: noop, - error: noop, - image: noop, - log: noop, - logImportant: noop, - onCustomCommand: noop, - overlay: noop, - reportError: noop, - send: noop, - startTimer: noop, - storybookSwitcher: noop, - use: noop, - useReactNative: noop, - warn: noop, - } -} - -/** - * You'll probably never use the service like this since we hang the Reactotron - * instance off of `console.tron`. This is only to be consistent with the other - * services. - */ -export class Reactotron { - config: ReactotronConfig - - rootStore: any - - /** - * Create the Reactotron service. - * - * @param config the configuration - */ - constructor(config: ReactotronConfig = DEFAULT_REACTOTRON_CONFIG) { - // merge the passed in config with some defaults - this.config = { - host: 'localhost', - useAsyncStorage: true, - ...config, - state: { - initial: false, - snapshots: false, - ...(config && config.state), - }, - } - } - - /** - * Hook into the root store for doing awesome state-related things. - * - * @param rootStore The root store - */ - setRootStore(rootStore: any, initialData: any) { - if (__DEV__) { - rootStore = rootStore as RootStore // typescript hack - this.rootStore = rootStore - - const { initial, snapshots } = this.config.state - const name = 'ROOT STORE' - - // logging features - if (initial) { - console.tron.display({ - name, - value: initialData, - preview: 'Initial State', - }) - } - // log state changes? - if (snapshots) { - onSnapshot(rootStore, (snapshot) => { - console.tron.display({ name, value: snapshot, preview: 'New State' }) - }) - } - - console.tron.trackMstNode(rootStore) - } - } - - /** - * Configure reactotron based on the the config settings passed in, then connect if we need to. - */ - async setup() { - // only run this in dev... metro bundler will ignore this block: 🎉 - if (__DEV__) { - // configure reactotron - Tron.configure({ - name: this.config.name || require('../../../package.json').name, - host: this.config.host, - }) - - // hookup middleware - if (Platform.OS !== 'web') { - if (this.config.useAsyncStorage) { - Tron.setAsyncStorageHandler(AsyncStorage) - } - Tron.useReactNative({ - asyncStorage: this.config.useAsyncStorage ? undefined : false, - }) - } - - // ignore some chatty `mobx-state-tree` actions - const RX = /postProcessSnapshot|@APPLY_SNAPSHOT/ - - // hookup mobx-state-tree middleware - Tron.use( - mst({ - filter: (event) => RX.test(event.name) === false, - }), - ) - - // connect to the app - Tron.connect() - - // Register Custom Commands - Tron.onCustomCommand({ - title: 'Reset Root Store', - description: 'Resets the MST store', - command: 'resetStore', - handler: () => { - console.tron.log('resetting store') - clear() - }, - }) - - Tron.onCustomCommand({ - title: 'Reset Navigation State', - description: 'Resets the navigation state', - command: 'resetNavigation', - handler: () => { - console.tron.log('resetting navigation state') - RootNavigation.resetRoot({ routes: [] }) - }, - }) - - Tron.onCustomCommand({ - title: 'Go Back', - description: 'Goes back', - command: 'goBack', - handler: () => { - console.tron.log('Going back') - RootNavigation.goBack() - }, - }) - - // clear if we should - if (this.config.clearOnLoad) { - Tron.clear() - } - } - } -} diff --git a/app_expo/services/reactotron/tron.ts b/app_expo/services/reactotron/tron.ts deleted file mode 100644 index 6086e48..0000000 --- a/app_expo/services/reactotron/tron.ts +++ /dev/null @@ -1,2 +0,0 @@ -import Reactotron from 'reactotron-react-native' -export const Tron = Reactotron diff --git a/app_expo/services/reactotron/tron.web.ts b/app_expo/services/reactotron/tron.web.ts deleted file mode 100644 index a525c06..0000000 --- a/app_expo/services/reactotron/tron.web.ts +++ /dev/null @@ -1,2 +0,0 @@ -import Reactotron from 'reactotron-react-js' -export const Tron = Reactotron |