@@ -12,7 +12,7 @@ const db = new Datastore({
1212
1313// cleaning cache data on app restart
1414db . remove (
15- { $or : [ { data : { } } , { data : "Unknown symbol" } ] } ,
15+ { $or : [ { stockData : { } } , { stockData : "Unknown symbol" } ] } ,
1616 { multi : true } ,
1717 ( err , count ) => {
1818 console . log ( "\nremoving garbage from cache..." ) ;
@@ -31,10 +31,12 @@ const getUID = (n = 8, symbols = _symbols) =>
3131 . map ( ( ) => symbols [ Math . floor ( Math . random ( ) * symbols . length ) ] )
3232 . join ( "" ) ;
3333
34- const { IEX_API_KEY = "" , CACHE_TTL_MINUTES = 10 } = process . env ;
34+ const { ALPHA_VANTAGE_API_KEY = "" , CACHE_TTL_MINUTES = 10 } = process . env ;
3535
3636const validTickerRegExp = / ^ [ a - z ] { 1 , 6 } $ / ;
37- const isValidStock = stock => validTickerRegExp . test ( stock ) ;
37+ const isValidStock = ( stock ) => validTickerRegExp . test ( stock ) ;
38+ const parseFloatAndRound = ( value , digits ) =>
39+ Number ( parseFloat ( value ) . toFixed ( digits ) ) ;
3840
3941router . use ( cors ( ) ) ;
4042
@@ -60,30 +62,78 @@ router.get("/stock/:stock/quote", (req, res, next) => {
6062 if ( err ) return next ( err ) ;
6163 if ( cached ) {
6264 console . log ( `rid: ${ req_id } ** ${ stock } from cache **` ) ;
63- return res . json ( cached . data ) ;
65+ return res . json ( cached . stockData ) ;
6466 }
6567 try {
6668 const { data } = await axios . get (
67- `https://cloud.iexapis.com/stable/stock/ ${ stock } /quote?token =${ IEX_API_KEY } `
69+ `https://www.alphavantage.co/query?function=GLOBAL_QUOTE&symbol= ${ stock } &apikey =${ ALPHA_VANTAGE_API_KEY } `
6870 ) ;
6971 console . log ( `rid: ${ req_id } !! ${ stock } from api !!` ) ;
70- res . json ( data ) ;
72+ const temp = { ...data ?. [ "Global Quote" ] } ;
73+ let stockData ;
74+ if ( Object . keys ( temp ) . length === 0 && temp . constructor === Object ) {
75+ stockData = "Unknown symbol" ; // Mimic IEX API response for this case
76+ } else {
77+ const symbol = temp [ "01. symbol" ] ;
78+ const open = parseFloatAndRound ( temp [ "02. open" ] , 2 ) ;
79+ const high = parseFloatAndRound ( temp [ "03. high" ] , 2 ) ;
80+ const low = parseFloatAndRound ( temp [ "04. low" ] , 2 ) ;
81+ const close = parseFloatAndRound ( temp [ "05. price" ] , 2 ) ;
82+ const volume = Number ( parseFloatAndRound ( temp [ "06. volume" ] ) , 2 ) ;
83+ const latestTime = new Date (
84+ temp [ "07. latest trading day" ]
85+ ) . toLocaleString ( "en-US" , {
86+ month : "long" ,
87+ day : "numeric" ,
88+ year : "numeric"
89+ } ) ;
90+ const previousClose = parseFloatAndRound (
91+ temp [ "08. previous close" ] ,
92+ 2
93+ ) ;
94+ const change = parseFloatAndRound ( temp [ "09. change" ] , 2 ) ;
95+
96+ // Transform the response to match the IEX's as closely as possible
97+ // with the available data
98+ stockData = {
99+ change,
100+ changePercent : parseFloatAndRound (
101+ ( close - previousClose ) / previousClose ,
102+ 5
103+ ) ,
104+ close,
105+ high,
106+ latestPrice : close ,
107+ latestTime,
108+ latestVolume : volume ,
109+ low,
110+ open,
111+ previousClose,
112+ symbol,
113+ volume
114+ } ;
115+ }
116+ res . json ( stockData ) ;
71117 db . update (
72118 {
73119 _id : stock
74120 } ,
75- { _id : stock , data , updatedAt : Date . now ( ) } ,
121+ { _id : stock , stockData , updatedAt : Date . now ( ) } ,
76122 { upsert : true } ,
77123 ( ) => console . log ( `rid: ${ req_id } ++ ${ stock } stored ++` )
78124 ) ;
79125 } catch ( e ) {
80126 if ( e . response ) {
81- res . status ( e . response . status ) . json ( e . response . data ) ;
127+ res . status ( e . response . status ) . json ( e . response . stockData ) ;
82128 db . update (
83129 {
84130 _id : stock
85131 } ,
86- { _id : stock , data : e . response . data , updatedAt : Date . now ( ) } ,
132+ {
133+ _id : stock ,
134+ stockData : e . response . stockData ,
135+ updatedAt : Date . now ( )
136+ } ,
87137 { upsert : true }
88138 ) ;
89139 } else {
0 commit comments