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<UseCase> {
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<U extends typeof MainUseCase>(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<U>
}
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<StoreState>({
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<StoreState>({
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<UIState>({
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);
})
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)}
.



No Comments