diff --git a/src/auth.ts b/src/auth.ts index 5a6e39d..862012b 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -16,6 +16,7 @@ import { error, info, warn } from './cli/messages'; import { loginSelection } from './cli/selection'; import { Config, save } from './config'; import { ErrorCode } from './deploy'; +import { logout } from './logout'; import { forever } from './utils'; const authToken = async (config: Config): Promise => { @@ -54,8 +55,17 @@ const authToken = async (config: Config): Promise => { } if (expiresIn(token) < config.renewTime) { - // Token expires in < renewTime - token = await api.refresh(); + try { + // Attempt to refresh token + token = await api.refresh(); + token && (await save({ token })); + } catch (err) { + await logout(); + info('Token expired. Please login again.'); + // Pass isReLogin as true + const newToken = await authSelection(config, true); + await save({ token: newToken }); + } } return token; @@ -169,7 +179,10 @@ const authSignup = async (config: Config): Promise => { return process.exit(ErrorCode.Ok); }; -const authSelection = async (config: Config): Promise => { +export const authSelection = async ( + config: Config, + isReLogin = false +): Promise => { const token = await (async () => { if (args['email'] || args['password']) { return await authLogin(config); @@ -180,7 +193,7 @@ const authSelection = async (config: Config): Promise => { { 'Login by token': authToken, 'Login by email and password': authLogin, - 'New user, sign up': authSignup + ...(isReLogin ? {} : { 'New user, sign up': authSignup }) }; return await methods[await loginSelection(Object.keys(methods))]( diff --git a/src/cli/selection.ts b/src/cli/selection.ts index 03142fd..94a8a31 100644 --- a/src/cli/selection.ts +++ b/src/cli/selection.ts @@ -6,12 +6,17 @@ import { import { Plans } from '@metacall/protocol/plan'; import { prompt } from 'inquirer'; -export const loginSelection = (methods: string[]): Promise => +export const loginSelection = ( + methods: string[], + isReLogin = false +): Promise => prompt<{ method: string }>([ { type: 'list', name: 'method', - message: 'Select the login method', + message: isReLogin + ? 'Token expired. Select login method' + : 'Select the login method', choices: methods } ]).then((res: { method: string }) => res.method); diff --git a/src/cli/validateToken.ts b/src/cli/validateToken.ts index 122ffca..2eaa86d 100644 --- a/src/cli/validateToken.ts +++ b/src/cli/validateToken.ts @@ -1,22 +1,38 @@ import { API as APIInterface } from '@metacall/protocol/protocol'; import { unlink } from 'fs/promises'; -import { configFilePath, save } from '../config'; +import { authSelection } from '../auth'; +import { Config, configFilePath, save } from '../config'; +import { logout } from '../logout'; import { exists } from '../utils'; import args from './args'; import { error, info } from './messages'; -const handleValidateToken = async (api: APIInterface): Promise => { +const handleValidateToken = async ( + api: APIInterface, + config: Config +): Promise => { const validToken = await api.validate(); if (!validToken) { - const token = await api.refresh(); - await save({ token }); + try { + const token = await api.refresh(); + token && (await save({ token })); + } catch (err) { + await logout(); + info('Token expired. Please login again.'); + // Pass isReLogin as true + const newToken = await authSelection(config, true); + await save({ token: newToken }); + } } }; -const validateToken = async (api: APIInterface): Promise => { +const validateToken = async ( + api: APIInterface, + config: Config +): Promise => { try { - await handleValidateToken(api); + await handleValidateToken(api, config); } catch (err) { if (args['dev']) { info( diff --git a/src/index.ts b/src/index.ts index 3ab86b4..d172c51 100644 --- a/src/index.ts +++ b/src/index.ts @@ -44,7 +44,7 @@ void (async () => { args['dev'] ? config.devURL : config.baseURL ); - await validateToken(api); + await validateToken(api, config); if (args['listPlans']) return await listPlans(api);