From 98bdfdbbebfab1228b6f3830eeb328a7cfb01b9d Mon Sep 17 00:00:00 2001 From: soun059 Date: Thu, 22 Aug 2024 12:20:57 +0530 Subject: [PATCH] Convert remaining identifier javascript code to typescript Convert remaining identifier javascript code to typescript and add all possible type notations as installation packages. --- .../src/actions/{common.js => common.ts} | 14 ++++--- identifier/src/actions/{login.js => login.ts} | 42 ++++++++++--------- identifier/src/actions/{types.js => types.ts} | 0 identifier/src/actions/{utils.js => utils.ts} | 9 ++-- identifier/src/errors/{index.js => index.ts} | 8 ++-- identifier/src/models/{hello.js => hello.ts} | 6 +-- .../src/reducers/{common.js => common.ts} | 19 ++++++++- .../src/reducers/{index.js => index.ts} | 0 .../src/reducers/{login.js => login.ts} | 12 +++++- identifier/src/store.js | 24 ----------- identifier/src/store.ts | 34 +++++++++++++++ 11 files changed, 104 insertions(+), 64 deletions(-) rename identifier/src/actions/{common.js => common.ts} (86%) rename identifier/src/actions/{login.js => login.ts} (82%) rename identifier/src/actions/{types.js => types.ts} (100%) rename identifier/src/actions/{utils.js => utils.ts} (57%) rename identifier/src/errors/{index.js => index.ts} (91%) rename identifier/src/models/{hello.js => hello.ts} (75%) rename identifier/src/reducers/{common.js => common.ts} (75%) rename identifier/src/reducers/{index.js => index.ts} (100%) rename identifier/src/reducers/{login.js => login.ts} (82%) delete mode 100644 identifier/src/store.js create mode 100644 identifier/src/store.ts diff --git a/identifier/src/actions/common.js b/identifier/src/actions/common.ts similarity index 86% rename from identifier/src/actions/common.js rename to identifier/src/actions/common.ts index 49e6beb8..ce35b9d0 100644 --- a/identifier/src/actions/common.js +++ b/identifier/src/actions/common.ts @@ -10,8 +10,10 @@ import { import { handleAxiosError } from './utils'; import * as types from './types'; +import { Dispatch } from 'redux'; +import { AppDispatch, RootState } from '../store'; -export function receiveError(error) { +export function receiveError(error: any) { return { type: types.RECEIVE_ERROR, error @@ -24,7 +26,7 @@ export function resetHello() { }; } -export function receiveHello(hello) { +export function receiveHello(hello: {success?: boolean, username: string, displayName?: string}) { const { success, username, displayName } = hello; return { @@ -37,7 +39,7 @@ export function receiveHello(hello) { } export function executeHello() { - return function(dispatch, getState) { + return function(dispatch:Dispatch , getState: () => RootState) { dispatch(resetHello()); const { flow, query } = getState().common; @@ -78,7 +80,7 @@ export function executeHello() { } export function retryHello() { - return function(dispatch) { + return function(dispatch: AppDispatch) { dispatch(receiveError(null)); return dispatch(executeHello()); @@ -91,7 +93,7 @@ export function requestLogoff() { }; } -export function receiveLogoff(state) { +export function receiveLogoff(state: boolean) { return { type: types.RECEIVE_LOGOFF, state @@ -99,7 +101,7 @@ export function receiveLogoff(state) { } export function executeLogoff() { - return function(dispatch) { + return function(dispatch: AppDispatch) { dispatch(resetHello()); dispatch(requestLogoff()); diff --git a/identifier/src/actions/login.js b/identifier/src/actions/login.ts similarity index 82% rename from identifier/src/actions/login.js rename to identifier/src/actions/login.ts index b57b1aaa..9715c71b 100644 --- a/identifier/src/actions/login.js +++ b/identifier/src/actions/login.ts @@ -15,12 +15,13 @@ import { import * as types from './types'; import { receiveHello } from './common'; import { handleAxiosError } from './utils'; +import { AppDispatch, PromiseDispatch, RootState } from '../store'; // Modes for logon. export const ModeLogonUsernameEmptyPasswordCookie = '0'; export const ModeLogonUsernamePassword = '1'; -export function updateInput(name, value) { +export function updateInput(name: string, value?: string | null) { return { type: types.UPDATE_INPUT, name, @@ -28,14 +29,14 @@ export function updateInput(name, value) { }; } -export function receiveValidateLogon(errors) { +export function receiveValidateLogon(errors: {[key: string]: any}) { return { type: types.RECEIVE_VALIDATE_LOGON, errors }; } -export function requestLogon(username, password) { +export function requestLogon(username: string, password: string) { return { type: types.REQUEST_LOGON, username, @@ -43,7 +44,7 @@ export function requestLogon(username, password) { }; } -export function receiveLogon(logon) { +export function receiveLogon(logon: {success: boolean, errors: {http: any}}) { const { success, errors } = logon; return { @@ -59,7 +60,7 @@ export function requestConsent(allow=false) { }; } -export function receiveConsent(logon) { +export function receiveConsent(logon: {success: boolean, errors: {http: any}}) { const { success, errors } = logon; return { @@ -69,8 +70,8 @@ export function receiveConsent(logon) { }; } -export function executeLogon(username, password, mode=ModeLogonUsernamePassword) { - return function(dispatch, getState) { +export function executeLogon(username: string, password: string, mode=ModeLogonUsernamePassword) { + return function(dispatch: AppDispatch, getState: () => RootState) { dispatch(requestLogon(username, password)); dispatch(receiveHello({ username @@ -151,7 +152,7 @@ export function executeLogon(username, password, mode=ModeLogonUsernamePassword) } export function executeConsent(allow=false, scope='') { - return function(dispatch, getState) { + return function(dispatch: AppDispatch, getState: () => RootState) { dispatch(requestConsent(allow)); const { query } = getState().common; @@ -205,10 +206,10 @@ export function executeConsent(allow=false, scope='') { }; } -export function validateUsernamePassword(username, password, isSignedIn) { - return function(dispatch) { +export function validateUsernamePassword(username: string, password: string, isSignedIn: boolean) { + return function(dispatch: AppDispatch) { return new Promise((resolve, reject) => { - const errors = {}; + const errors:{[key: string]: any} = {}; if (!username) { errors.username = new Error(ERROR_LOGIN_VALIDATE_MISSINGUSERNAME); @@ -227,14 +228,14 @@ export function validateUsernamePassword(username, password, isSignedIn) { }; } -export function executeLogonIfFormValid(username, password, isSignedIn) { - return (dispatch) => { +export function executeLogonIfFormValid(username: string, password: string, isSignedIn: boolean) { + return (dispatch: PromiseDispatch) => { return dispatch( validateUsernamePassword(username, password, isSignedIn) ).then(() => { const mode = isSignedIn ? ModeLogonUsernameEmptyPasswordCookie : ModeLogonUsernamePassword; return dispatch(executeLogon(username, password, mode)); - }).catch((errors) => { + }).catch((errors: any) => { return { success: false, errors: errors @@ -243,8 +244,9 @@ export function executeLogonIfFormValid(username, password, isSignedIn) { }; } -export function advanceLogonFlow(success, history, done=false, extraQuery={}) { - return (dispatch, getState) => { + +export function advanceLogonFlow(success: boolean, history: any, done=false, extraQuery={}) { + return (dispatch:AppDispatch, getState: () => RootState) => { if (!success) { return; } @@ -256,16 +258,16 @@ export function advanceLogonFlow(success, history, done=false, extraQuery={}) { case 'oauth': case 'consent': case 'oidc': - if (hello.details.flow !== flow) { + if (hello?.details.flow !== flow) { // Ignore requested flow if hello flow does not match. break; } - if (!done && hello.details.next === 'consent') { + if (!done && hello?.details.next === 'consent') { history.replace(`/consent${history.location.search}${history.location.hash}`); return; } - if (hello.details.continue_uri) { + if (hello?.details.continue_uri) { q.prompt = 'none'; window.location.replace(hello.details.continue_uri + '?' + queryString.stringify(q)); return; @@ -276,7 +278,7 @@ export function advanceLogonFlow(success, history, done=false, extraQuery={}) { default: // Legacy stupid modes. if (q.continue && q.continue.indexOf(document.location.origin) === 0) { - window.location.replace(q.continue); + window.location.replace(q.continue as string); return; } } diff --git a/identifier/src/actions/types.js b/identifier/src/actions/types.ts similarity index 100% rename from identifier/src/actions/types.js rename to identifier/src/actions/types.ts diff --git a/identifier/src/actions/utils.js b/identifier/src/actions/utils.ts similarity index 57% rename from identifier/src/actions/utils.js rename to identifier/src/actions/utils.ts index d91c04a0..9df82e41 100644 --- a/identifier/src/actions/utils.js +++ b/identifier/src/actions/utils.ts @@ -1,14 +1,15 @@ +import { AxiosError } from 'axios'; import { ExtendedError, ERROR_HTTP_NETWORK_ERROR, ERROR_HTTP_UNEXPECTED_RESPONSE_STATUS } from '../errors'; -export function handleAxiosError(error) { - if (error.request) { +export function handleAxiosError(error: AxiosError | ExtendedError) { + if ((error as AxiosError).request) { // Axios errors. - if (error.response) { - error = new ExtendedError(ERROR_HTTP_UNEXPECTED_RESPONSE_STATUS, error.response); + if ((error as AxiosError).response) { + error = new ExtendedError(ERROR_HTTP_UNEXPECTED_RESPONSE_STATUS, (error as AxiosError).response); } else { error = new ExtendedError(ERROR_HTTP_NETWORK_ERROR); } diff --git a/identifier/src/errors/index.js b/identifier/src/errors/index.ts similarity index 91% rename from identifier/src/errors/index.js rename to identifier/src/errors/index.ts index f7ca6a97..2d2bef1d 100644 --- a/identifier/src/errors/index.js +++ b/identifier/src/errors/index.ts @@ -1,5 +1,7 @@ /* eslint react/prop-types: 0 */ +import { TFunction } from 'i18next'; +import { ComponentType } from 'react'; import { withTranslation } from 'react-i18next'; export const ERROR_LOGIN_VALIDATE_MISSINGUSERNAME = 'konnect.error.login.validate.missingUsername'; @@ -13,7 +15,7 @@ export const ERROR_HTTP_UNEXPECTED_RESPONSE_STATE = 'konnect.error.http.unexpect export class ExtendedError extends Error { values = undefined; - constructor(message, values) { + constructor(message: string, values: any) { super(message); if (Error.captureStackTrace !== undefined) { Error.captureStackTrace(this, ExtendedError); @@ -23,7 +25,7 @@ export class ExtendedError extends Error { } // Component to translate error text with values. -function ErrorMessageComponent(props) { +function ErrorMessageComponent(props: { error?:any, t: TFunction, values: any }) { const { error, t, values } = props; if (!error) { @@ -60,4 +62,4 @@ function ErrorMessageComponent(props) { return f(messageDescriptor.defaultMessage, messageDescriptor.values); } -export const ErrorMessage = withTranslation()(ErrorMessageComponent); +export const ErrorMessage = withTranslation()(ErrorMessageComponent as ComponentType); diff --git a/identifier/src/models/hello.js b/identifier/src/models/hello.ts similarity index 75% rename from identifier/src/models/hello.js rename to identifier/src/models/hello.ts index dab2ad09..903b2235 100644 --- a/identifier/src/models/hello.js +++ b/identifier/src/models/hello.ts @@ -1,12 +1,12 @@ -export function newHelloRequest(flow, query) { - const r = {}; +export function newHelloRequest(flow: string, query: {scope?: string, client_id?: string, redirect_uri: string, id_token_hint?: string, max_age?: string,claims_scope?: string, prompt?: any }) { + const r:{[key: string]: string} = {}; if (query.prompt) { // TODO(longsleep): Validate prompt values? r.prompt = query.prompt; } - let selectedFlow = flow; + let selectedFlow: string | null = flow; switch (flow) { case 'oauth': case 'consent': diff --git a/identifier/src/reducers/common.js b/identifier/src/reducers/common.ts similarity index 75% rename from identifier/src/reducers/common.js rename to identifier/src/reducers/common.ts index 58b49f64..454c8891 100644 --- a/identifier/src/reducers/common.js +++ b/identifier/src/reducers/common.ts @@ -20,7 +20,22 @@ const defaultPathPrefix = (() => { return pathPrefix; })(); -const defaultState = { +type commonStateType = { + hello: { + state: any, + username: string, + displayName: string, + details: any + } | null, + branding: string | null, + error: any, + flow: string | (string | null)[], + query: queryString.ParsedQuery, + pathPrefix: string, + updateAvailable: boolean +} + +const defaultState:commonStateType = { hello: null, branding: null, error: null, @@ -30,7 +45,7 @@ const defaultState = { pathPrefix: defaultPathPrefix }; -function commonReducer(state = defaultState, action) { +function commonReducer(state = defaultState, action: {type: string, error: any, state: any, username: string, displayName: string, hello: any}) { switch (action.type) { case RECEIVE_ERROR: return Object.assign({}, state, { diff --git a/identifier/src/reducers/index.js b/identifier/src/reducers/index.ts similarity index 100% rename from identifier/src/reducers/index.js rename to identifier/src/reducers/index.ts diff --git a/identifier/src/reducers/login.js b/identifier/src/reducers/login.ts similarity index 82% rename from identifier/src/reducers/login.js rename to identifier/src/reducers/login.ts index 8ad64786..53e76587 100644 --- a/identifier/src/reducers/login.js +++ b/identifier/src/reducers/login.ts @@ -9,12 +9,20 @@ import { UPDATE_INPUT } from '../actions/types'; -function loginReducer(state = { + +type loginState = { + loading: string, + username: string, + password: string, + errors: {[key: string] : string} +} + +function loginReducer(state:loginState = { loading: '', username: '', password: '', errors: {} -}, action) { +}, action: {errors: any, type: string, success?: boolean, name: string, value: any}) { switch (action.type) { case RECEIVE_VALIDATE_LOGON: return Object.assign({}, state, { diff --git a/identifier/src/store.js b/identifier/src/store.js deleted file mode 100644 index 1fde7bfd..00000000 --- a/identifier/src/store.js +++ /dev/null @@ -1,24 +0,0 @@ -import { createStore, applyMiddleware, compose } from 'redux'; -import thunkMiddleware from 'redux-thunk'; -import { createLogger } from 'redux-logger'; - -import rootReducer from './reducers'; - -const middlewares = [ - thunkMiddleware -]; - -if (process.env.NODE_ENV !== 'development') { // eslint-disable-line no-undef - middlewares.push(createLogger()); // must be last middleware in the chain. -} - -const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose; - -const store = createStore( - rootReducer, - composeEnhancers(applyMiddleware( - ...middlewares, - )) -); - -export default store; diff --git a/identifier/src/store.ts b/identifier/src/store.ts new file mode 100644 index 00000000..efaefedb --- /dev/null +++ b/identifier/src/store.ts @@ -0,0 +1,34 @@ +import { createStore, applyMiddleware, compose, Middleware, AnyAction, Action, Dispatch } from 'redux'; +import thunkMiddleware, { ThunkAction, ThunkDispatch, ThunkMiddleware } from 'redux-thunk'; +import { createLogger } from 'redux-logger'; + +import rootReducer from './reducers'; + +declare global { + interface Window { + __REDUX_DEVTOOLS_EXTENSION_COMPOSE__?: typeof compose; + } +} + +const middlewares: (Middleware<{}, any, any> | (ThunkMiddleware & { withExtraArgument = AnyAction>(extraArgument: ExtraThunkArg): ThunkMiddleware; }))[] = [ + thunkMiddleware +]; + +if (process.env.NODE_ENV !== 'development') { // eslint-disable-line no-undef + middlewares.push(createLogger()); // must be last middleware in the chain. +} + +const composeEnhancers = (window['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__'] as typeof compose) || compose || compose; + +const store = createStore( + rootReducer, + composeEnhancers(applyMiddleware( + ...middlewares, + )) +); + +export type RootState = ReturnType +export type AppDispatch = typeof store.dispatch; +export type PromiseDispatch = ThunkDispatch; + +export default store;