Consumo de API do Curió Consumo API Curió no React Native Setup do Curió no App 1º Passo: Criar uma pasta de configuração na raiz do projeto. 2º Passo: Criar um arquivo de configuração na pasta config criada. Exemplo: { "service": { "url": "https://srvd1.dev.evologica.com.br/cxClient/cxIsapiClient.dll/gatewayJSON?version=3", "server": "192.168.0.49", // Trocar para o IP do PC que está rodando o serviço "system": 53, "port": 5563 }, "accessToken": "2CEAE6DE538FB283817C48F449C49D5D7D2BDE2A886406FCD6C5566DB34CE8EA", "resources": { "get": "https://srvd1.dev.evologica.com.br/cxClient/cxIsapiClient.dll/getpr?id=", "put": "https://srvd1.dev.evologica.com.br/cxClient/cxIsapiClient.dll/putpr", "viewer": "https://srvd1.dev.evologica.com.br/relatorios/viewer/rel.html?id=" }, "logs": true } 3º Passo: Criar uma pasta chamada core dentro da pasta src do projeto. 4º Passo: Criar uma pasta chamada curio dentro da pasta core, e, dentro da pasta curio, adicione os dois arquivos index.ts e SessionManager.ts conforme a imagem. 5º Passo: Dentro do arquivo index.ts adicione o código: import { Platform } from 'react-native' import { Dispatch } from 'redux' import { FetchLink } from '@curio/client/links' import { V3RequestParser } from '@curio/client/parsers' import { createV3Validator } from '@curio/client/validators' import config from '../../config/default.json' import { SessionManager } from './SessionManager' import { store } from '../redux' let sessionManager: SessionManager const createSessionManager = (dispatch: Dispatch, configuration = config) => { const link = new FetchLink(configuration.service) const requestParser = new V3RequestParser(configuration.service) sessionManager = new SessionManager( configuration.service, (request) => { return Promise.resolve(request) .then(requestParser.parse) .then(JSON.stringify) .then(link.parse) .then(link.post) .then((response) => response.json()) .then(json => { return json }) .then(createV3Validator(request).validate) }, dispatch ) interface Attributes { [index: string]: string _Id: string _Recipient: string _Sender: string _SerialNumber: string _SignalName: string } if (config.logs) { sessionManager[Symbol.observable]().subscribe({ next: (msg) => { if (!Number(msg.signalName)) { const signalName = msg.signalName.substr(msg.signalName.indexOf('_') + 1).replace(/_/g, ' ') const filteredBody = Object.keys(msg.body ? (msg.body as Attributes) : {}).reduce((acc, curr) => { if (curr.indexOf('_') < 0) return { ...acc, [curr]: (msg.body as Attributes)[curr] } else return acc }, {}) const colorType = msg.type === 'response' ? 'green' : 'blue' // console.log( // `%c ${msg.type.toUpperCase()} %c ${signalName}`, // `color: white; font-weight: bolder; background: ${colorType}`, // 'font-weight: bolder; font-style: italic;', // Object.keys(filteredBody).length !== 0 ? filteredBody : '' // ) } }, error: (msg) => { if (!Number(msg.signalName)) { const signalName = msg.signalName.substr(msg.signalName.indexOf('_') + 1).replace(/_/g, ' ') const colorType = 'red' // console.log( // `%c ${msg.type.toUpperCase()} %c ${signalName}`, // `color: white; font-weight: bolder; background: ${colorType}`, // 'font-weight: bolder; font-style: italic;', // msg.error.message // ) } }, complete: () => console.log('complete'), }) } } export { sessionManager, createSessionManager } export default config 6º Passo: Dentro do arquivo SessionManager.ts adicione o código: import { Dispatch } from 'redux' import { MainUseCase, RequestDriver, SecurityManager, Service, UseCase, UseCaseMessageType } from '@curio/client' import { ConnectionError, DestinataryNotFoundError } from '@curio/client/errors' import { ABORT, OPEN } from '@curio/client/utils/constants' import { actions as sessionActions } from '../redux/session' import AsyncStorage from '@react-native-async-storage/async-storage' export const STORAGE_SESSION_KEY = 'br.com.environlink.sensor' // Trocar essa chave para usar a da aplicação que desejar export class AnonymousSession extends MainUseCase {} export class SessionManager extends SecurityManager { public session: MainUseCase | undefined private _dispatch: Dispatch constructor(service: Service, driver: RequestDriver, dispatch: Dispatch) { super(service, driver) this._dispatch = dispatch } public async openAnonymousUseCase(useCaseId: string | number): Promise { const id = await this.sendRequest(OPEN, { USECASEID: useCaseId, GUIID: 0, SYSTEM_CODE: this.service.system.toString(), }) const uc = new UseCase(id) uc.driver = this.driver return uc } public async openMainUseCase(username: string, password: string, constructor?: U) { this.session = await super.openMainUseCase(username, password, constructor) await AsyncStorage.setItem(STORAGE_SESSION_KEY, this.session!.token.toString()) this.session!.addListener(ABORT, () => this._unauthenticate(false)) this.session!.addListener(UseCaseMessageType.RESPONSE, (message: any) => { if (message.error instanceof DestinataryNotFoundError || message.error instanceof ConnectionError) { this._unauthenticate(true) } }) return this.session! as InstanceType } public connectMainUseCase(mainUseCase: MainUseCase) { this.session = mainUseCase if (!(mainUseCase instanceof AnonymousSession)) { AsyncStorage.setItem(STORAGE_SESSION_KEY, this.session!.token.toString()).then().catch(console.error) } this.session.addListener(ABORT, () => this._unauthenticate(false)) this.session.addListener(UseCaseMessageType.RESPONSE, (message: any) => { if (message.error instanceof DestinataryNotFoundError || message.error instanceof ConnectionError) { this._unauthenticate(true) } }) return super.connectMainUseCase(mainUseCase) } private _unauthenticate(expired: boolean) { AsyncStorage.removeItem(STORAGE_SESSION_KEY) if (expired) { this._dispatch(sessionActions.logout()) } this.session = undefined } } Setup Redux no App 1º Passo: Instalar as seguintes bibliotecas do Redux na aplicação: - react-redux - redux - @reduxjs/toolkit - redux-devtools-extension - redux-logger - redux-persist OBS: Caso esteja usando Typescript, baixe as dependências de desenvolvimento a seguir: - @types/react-redux - @types/redux - @types/redux-logger 2º Passo Criar uma pasta chamada redux com um arquivo index.ts e outro reducer.ts Insira o código a seguir no arquivo index.ts import { configureStore } from '@reduxjs/toolkit'; import AsyncStorage from '@react-native-async-storage/async-storage'; import { rootReducer, initialState, StoreState } from './reducer' import { createLogger } from 'redux-logger' export * from './reducer' AsyncStorage.removeItem('br.com.environlink.sensor.storage') // Trocar essa chave para usar a da aplicação que desejar const loggerMiddleware = createLogger({ collapsed: true }) const store = configureStore({ reducer: rootReducer, preloadedState: initialState, }); export { store }; Insira o código a seguir no arquivo reducers.ts import { combineReducers, PayloadAction } from '@reduxjs/toolkit' import entities, { EntitiesState, initialState as entitiesInitialState } from './entities' import { initialState as sessionInitialState, reducer as sessionReducer, State } from './session' import ui, { initialState as uiInitialState, UIState } from './ui' export interface StoreState { entities: EntitiesState session: State ui: UIState } export const initialState: StoreState = { session: sessionInitialState, ui: uiInitialState, entities: entitiesInitialState, } export const rootReducer = combineReducers({ session: sessionReducer, ui, entities, }) export { EntitiesTransform } from './entities' Chamando API de Login 1º Passo: Criar uma pasta chamada ui dentro da pasta redux e criar um arquivo index.ts nela contendo o código a seguir: import { combineReducers } from 'redux' import { initialState as contextInitialState, reducer as context, State as ContextState } from './context' import { initialState as credentialsInitialState, reducer as credentials, State as CredentialsState } from './credentials' import { initialState as errorInitialState, reducer as error, State as ErrorState } from './error' import { initialState as loginInitialState, reducer as login, State as LoginState } from './login' export * from './login' export interface UIState { error: ErrorState login: LoginState credentials: CredentialsState context: ContextState } const reducer = combineReducers({ login, error, credentials, context, }) export const initialState: UIState = { login: loginInitialState, error: errorInitialState, credentials: credentialsInitialState, context: contextInitialState, } export default reducer 2º Passo: Criar uma pasta login dentro da pasta ui com 3 arquivos: index.ts , reducer.ts e selectors.ts Insira o código a seguir no arquivo login/index.ts import { getTypesActions } from '../../../utils/reduxMethods' import login, { actions } from './reducer' import * as selectors from './selectors' export * from './reducer' const reducer = login.reducer const types = getTypesActions(actions) export { actions, reducer, types, selectors } export default login Insira o código a seguir no arquivo login/reducers.ts import { ActionType, reducerActions } from '../../../utils/reduxMethods' import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit' import { login } from '../../../core/api/useCases/login' import { createSessionManager } from '../../../core/curio' export interface State { login: boolean fetchingLogin: boolean error: boolean } export const initialState: State = { login: false, fetchingLogin: false, error: false } interface Login { username: string password: string } export interface ChangePassword { oldPassword: string newPassword: string onSuccess?(): void } type ChangePasswordReducer = ActionType< 'changePasswordRequest' | 'changePasswordSuccess' | 'changePasswordError', ChangePassword | undefined > const loginAction = createAsyncThunk('ui/login/action', async (payload: Login, thunkApi) => { await login(payload.username, payload.password); }) const initializeAction = createAsyncThunk('ui/login/initialize', (_, thunkApi) => { createSessionManager(thunkApi.dispatch); })![](http://docs.dev.evologica.com.br/loading.gif#uploadimage-7f0ab48e7561d) export const actions = { loginAction, initializeAction } const loginReducer = createSlice({ name: 'ui/login', initialState, reducers: { }, extraReducers: (builder) => { builder.addCase(loginAction.pending, (state) => { state.fetchingLogin = true state.login = true }); builder.addCase(loginAction.fulfilled, (state) => { state.fetchingLogin = false }); builder.addCase(loginAction.rejected, (state) => { state.error = true state.fetchingLogin = false }); } }) export default loginReducer Insira o código a seguir no arquivo login/selectors.ts import { State } from './reducer' export const isLogginIn = (state: State) => state.login 4ºPasso: Criar 2 estados utilizando useState(), um para username e outro 5ºPasso: No botão de login da sua tela, dispare a seguinte função: onPress={() => dispatch(loginActions.loginAction({ username, password }) as any)} .