How to handle DIRECT_LINE/POST_ACTIVITY_REJECTED - direct-line-botframework

I'm implementing webchat with token based along with chat persistence everything works fine when user is online, but after some idle time if user is offline with no internet connectivity, for about 30-45 mins then later he gets back online and when ever he texting anything bot went to state DIRECT_LINE/POST_ACTIVITY_REJECTED
and user was unable to chat with the bot its giving away send retry on my message bubble. Is there any way possible to handle?.
(async function() {
'use strict';
const {
hooks: { usePostActivity },
hooks: { useDirection },
ReactWebChat
} = window.WebChat;
let { token, conversation_Id } = sessionStorage;
if ( !token ) {
const res = await fetch( 'https:/localhost/api/generateToken', { method: 'POST' } );
const { token: directLineToken, conversationId: conversationId } = await res.json();
sessionStorage[ 'token' ] = directLineToken;
sessionStorage[ 'conversation_Id' ] = conversationId;
token = directLineToken;
conversation_Id = conversationId;
}
if (token) {
await setInterval(async () => {
var myHeaders = new Headers();
myHeaders.append("Authorization","Bearer "+ sessionStorage[ 'token' ]);
let res = await fetch( 'https://directline.botframework.com/v3/directline/tokens/refresh', {
method: 'POST',
headers: myHeaders,
});
const { token: directLineToken, conversationId } = await res.json();
sessionStorage[ 'token' ] = directLineToken;
sessionStorage[ 'conversation_Id' ] = conversationId;
token = directLineToken;
conversation_Id = conversationId;
}, 1000*60*15)}
const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
if(action.payload && action.payload.directLine) {
const subscription = action.payload.directLine.connectionStatus$.subscribe({
error: error => console.log( error ),
next: value => {
if ( value === 0 ) {console.log('Uninitialized')}
else if ( value === 1 ) {console.log('Connecting')}
else if ( value === 2 ) {console.log('Online')}
else if ( value === 3 ) {console.log('Expire Token')}
else if ( value === 4 ) {console.log('FailedToConnect')}
else if ( value === 5 ) {console.log('Ended')}
}
});
}
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'Welcome',
value: { language: window.navigator.language }
}
});
}
if (action.type === 'DIRECT_LINE/POST_ACTIVITY') {
action = window.simpleUpdateIn(action, ['payload', 'activity', 'channelData', 'CustomChannel'], () =>"webchat");
}
return next(action);
});
const botconnection = createDirectLine( {token,webSockets: true,watermark: "0" });
window.ReactDOM.render(
<ReactWebChat directLine={botconnection}
store={store}
/>,
document.getElementById('webchat'));
document.querySelector('#webchat > *').focus();
})().catch(err => console.error(err));
note: token is not expired and If I refresh the page bot starts reponding.

I made a few adjustments to the code you supplied. I believe your token value was getting overwritten or corrupted, so I separated out the assigning of the token in the API call (token) and the variable assignment in the script (dl_token).
I was also getting an error on the refresh token call wrapped in the setInterval() function, which is why I use Babel, as shown below. (For testing, it helps identify errors that would otherwise have been missed.). Removing the actual API call from setInterval() and calling it as a separate function seemed to fix this.
After these changes, everything seems to be working smoothly. I only tested a few times waiting until the 45-50 minute, but didn't experience any issues with the token, needing to refresh, or receiving DIRECT_LINE/POST_ACTIVITY_REJECTED.
(Note that I made calls to my own 'token' server for generating and refreshing the token.)
<script crossorigin="anonymous" src="https://unpkg.com/#babel/standalone#7.8.7/babel.min.js"></script>
<script type="text/babel" data-presets="es2015,react,stage-3">
( async function () {
'use strict';
const {
ReactWebChat
} = window.WebChat;
let { dl_token, conversation_Id } = sessionStorage;
if ( !dl_token ) {
const res = await fetch( 'http://localhost:3500/directline/conversations', { method: 'POST' } );
const { token, conversationId } = await res.json();
sessionStorage[ 'dl_token' ] = token;
sessionStorage[ 'conversation_Id' ] = conversationId;
dl_token = token;
conversation_Id = conversationId;
}
if ( dl_token === sessionStorage['dl_token'] ) {
setInterval( () => {
refreshToken()
}, 1000 * 60 * 1 )
}
const refreshToken = async () => {
const res = await fetch( 'http://localhost:3500/directline/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
token: dl_token
})
} );
const { token, conversationId } = await res.json();
sessionStorage[ 'dl_token' ] = token;
sessionStorage[ 'conversation_Id' ] = conversationId;
dl_token = token;
conversation_Id = conversationId;
}
const store = window.WebChat.createStore( {}, ( { dispatch } ) => next => action => {
if ( action.payload && action.payload.directLine ) {
const subscription = action.payload.directLine.connectionStatus$.subscribe( {
error: error => console.log( error ),
next: value => {
if ( value === 0 ) { console.log( 'Uninitialized' ) }
else if ( value === 1 ) { console.log( 'Connecting' ) }
else if ( value === 2 ) { console.log( 'Online' ) }
else if ( value === 3 ) { console.log( 'Expire Token' ) }
else if ( value === 4 ) { console.log( 'FailedToConnect' ) }
else if ( value === 5 ) { console.log( 'Ended' ) }
}
} );
}
if ( action.type === 'DIRECT_LINE/CONNECT_FULFILLED' ) {
dispatch( {
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'Welcome',
value: { language: window.navigator.language }
}
} );
}
if ( action.type === 'DIRECT_LINE/POST_ACTIVITY' ) {
action = window.simpleUpdateIn( action, [ 'payload', 'activity', 'channelData', 'CustomChannel' ], () => "webchat" );
}
return next( action );
} );
const botconnection = await createDirectLine( { token: dl_token } );
window.ReactDOM.render(
<ReactWebChat directLine={botconnection}
store={store}
/>,
document.getElementById( 'webchat' ) );
document.querySelector( '#webchat > *' ).focus();
} )().catch( err => console.error( err ) );
</script>
Hope of help!

Related

How can I build nodes and use them to create pages in gatsby?

I'm able to run my code in dev just fine and works as expected. Not sure what I'm doing wrong. Am I unable to create nodes and then build pages from them in gatsby-node.js? Is there a better way of doing this in gatsby that I'm not aware of?
The problem is when I try to build I receive error.
"gatsby-node.js" threw an error while running the sourceNodes lifecycle:
Request failed with status code 400
Here is my code:
exports.sourceNodes = async ({
actions,
createNodeId,
createContentDigest,
}) => {
const { createNode } = actions
const auth_token = Buffer.from(
`${client_id}:${client_secret}`,
'utf-8'
).toString('base64')
const token_url = 'https://accounts.spotify.com/api/token'
const data = qs.stringify({ grant_type: 'client_credentials' })
const response = await axios.post(token_url, data, {
headers: {
Authorization: `Basic ${auth_token}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
})
const access_token = await response.data.access_token
const spotifyData = await axios.get(
`https://api.spotify.com/v1/artists/${artistId}/albums`,
{
headers: {
Authorization: `Bearer ${access_token}`,
'Content-type': 'application/json',
},
params: {
limit: 50,
market: 'US',
groups: 'single,album',
},
}
)
const ALBUM_NODE_TYPE = `Album`
await spotifyData.data.items.forEach(album =>
createNode({
...album,
id: createNodeId(`${ALBUM_NODE_TYPE}-${album.id}`),
parent: null,
children: [],
internal: {
type: ALBUM_NODE_TYPE,
contentDigest: createContentDigest(album),
},
})
)
}
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const results = await graphql(`
{
collections: allFile {
distinct(field: sourceInstanceName)
edges {
node {
id
sourceInstanceName
childMarkdownRemark {
id
fields {
slug
}
frontmatter {
title
image
}
}
}
}
}
news: allFile(filter: { sourceInstanceName: { eq: "news" } }) {
nodes {
sourceInstanceName
childMarkdownRemark {
frontmatter {
title
image
blurb
url
}
id
fields {
slug
}
}
}
}
music: allAlbum(sort: { fields: release_date, order: DESC }) {
nodes {
id
href
images {
url
}
name
artists {
name
}
release_date
album_type
external_urls {
spotify
}
}
}
}
`)
// Music
await results.data.music.nodes.forEach(node => {
console.log(node)
if (node.errors) {
node.errors.forEach(e => console.error(e.toString()))
return Promise.reject(node.errors)
}
const id = node.id
const name = node.name.replace(/\s+/g, '_').toLowerCase()
createPage({
path: `music/${name}`,
component: path.resolve(`src/templates/music/music.js`),
// additional data can be passed via context
context: {
id,
field: { ...node },
},
})
})
await results.data.news.nodes.forEach(node => {
if (node.errors) {
node.errors.forEach(e => console.error(e.toString()))
return Promise.reject(node.errors)
}
const id = node.childMarkdownRemark.id
createPage({
path: `${node.sourceInstanceName}${node.childMarkdownRemark.fields.slug}`,
component: path.resolve(
`src/templates/${String(node.sourceInstanceName)}/${String(
node.sourceInstanceName
)}.js`
),
// additional data can be passed via context
context: {
id,
field: { ...node.childMarkdownRemark.frontmatter },
},
})
})
//News Collection
await results.data.collections.distinct.forEach(collection => {
if (collection.errors) {
collection.errors.forEach(e => console.error(e.toString()))
return Promise.reject(collection.errors)
} else {
if (collection !== 'news') {
return
} else {
const edges = results.data.collections.edges
const nodes = edges.filter(
e => e.node.sourceInstanceName === 'news'
)
createPage({
path: `/collections/news`,
component: path.resolve(
`src/templates/news/collections/news.js`
),
context: {
nodes: { ...nodes },
},
})
}
}
})
}
exports.onCreateNode = ({ node, actions, getNode }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const value = createFilePath({ node, getNode })
createNodeField({
name: `slug`,
node,
value,
})
}
}
I also tried wrapping the createPage function in sourceNodes but that didn't work either.
I ended up creating a source-plugin and passing in my Spotify credentials as a string in gatbsy-config.js. It's not able to read env variable at build time but it is when running dev and I'm not sure I understand why that is.

"Cannot read properties of null (reading 'token') " Reacjs, Redux

I am watching Brad Traversy MERN Tutorial. In which he has created a Goal Setter app. I have almost completed it but getting an error in reset() function of goalSlice. Dont know what the actual problem is. When the reset() is dispatch from the Dashboard.jsx, and after adding goals and viewing them in redux devtool in chrome. When I press logout button, the chrome gets hang and the console has this message Cannot read properties of null (reading 'token')
I believe this is the console.log(message) which is in Dashboard.jsx but i have no idea about resolving it. I tried commenting the dispatch(reset()) which removes this error, but I also have to reset the goals when user is logged out. Anyone have any idea about this??
I have uploaded my code on github aswell, so if anyone needs more info about code can visit this link : https://github.com/anishdalvi/MERN-Goal-Setter-.git
Youtube Link : https://youtu.be/UXjMo25Nnvc
Dashboard.jsx
import { useEffect } from 'react'
import { useNavigate } from 'react-router-dom'
import { useSelector, useDispatch } from 'react-redux'
import GoalForm from '../components/GoalForm'
import Spinner from '../components/Spinner'
import { getGoals, reset } from '../features/goals/goalSlice'
function Dashboard() {
const dispatch = useDispatch()
const navigate = useNavigate()
const { user } = useSelector((state) => state.auth)
const { goals, isLoading, isError, message } = useSelector((state) => state.goals)
useEffect(() => {
if(isError){
console.log("iserror "+ message)
}
if(!user){
navigate('/login')
}
dispatch(getGoals())
/* return () => {
dispatch(reset())
} */
} , [user, navigate, isError, message, dispatch] )
if (isLoading){
return <Spinner />
}
return (
<>
<section className="heading">
<h1>Welcome {user && user.name}</h1>
<p>Goals Dashboard</p>
</section>
<GoalForm />
</>
)
}
export default Dashboard
goalService.js
import axios from 'axios'
const API_URL = '/api/goals/'
// create new goal
const createGoal = async (goalData, token) => {
const config = {
headers: {
Authorization: `Bearer ${token}`
}
}
const response = await axios.post(API_URL, goalData, config)
return response.data
}
// get goals
const getGoals = async (token) => {
const config = {
headers: {
Authorization: `Bearer ${token}`
}
}
const response = await axios.get(API_URL, config)
return response.data
}
const goalService = {
createGoal,
getGoals
}
export default goalService
goalSlice.js
import { createSlice, createAsyncThunk } from '#reduxjs/toolkit'
import goalService from './goalService'
const initialState = {
goals: [],
isError: false,
isSuccess: false,
isLoading: false,
message: ""
}
// create new Goal
export const createGoal = createAsyncThunk('goals/create', async (goalData, thunkAPI) => {
try {
const token = thunkAPI.getState().auth.user.token
return await goalService.createGoal(goalData, token)
} catch (error) {
const message = (error.response && error.response.data && error.response.data.message) || error.message || error.toString()
return thunkAPI.rejectWithValue(message)
}
} )
// get user goals
export const getGoals = createAsyncThunk('goals/getAll', async(_, thunkAPI) => {
try {
const token = thunkAPI.getState().auth.user.token
return await goalService.getGoals(token)
} catch (error) {
const message = (error.response && error.response.data && error.response.data.message) || error.message || error.toString()
return thunkAPI.rejectWithValue(message)
}
})
export const goalSlice = createSlice({
name: 'goal',
initialState,
reducers: {
reset: (state) => initialState,
},
extraReducers:(builder) => {
builder
.addCase(createGoal.pending, (state) => {
state.isLoading = true
})
.addCase(createGoal.fulfilled, (state, action) => {
state.isLoading = false
state.isSuccess = true
state.goals.push(action.payload)
})
.addCase(createGoal.rejected, (state, action) => {
state.isLoading = false
state.isError = true
state.message = action.payload
})
.addCase(getGoals.pending, (state) => {
state.isLoading = true
})
.addCase(getGoals.fulfilled, (state, action) => {
state.isLoading = false
state.isSuccess = true
state.goals = action.payload
})
.addCase(getGoals.rejected, (state, action) => {
state.isLoading = false
state.isError = true
state.message = action.payload
})
}
})
export const { reset } = goalSlice.actions
export default goalSlice.reducer
authService.js
import axios from 'axios'
const API_URL = '/api/users/'
// Register User
const register = async (userData) => {
const response = await axios.post(API_URL, userData)
if(response.data){
localStorage.setItem('user', JSON.stringify(response.data))
}
return response.data
}
// login User
const login = async (userData) => {
const response = await axios.post(API_URL + 'login', userData)
if(response.data){
localStorage.setItem('user', JSON.stringify(response.data))
}
return response.data
}
// Logout User
const logout = () => {
localStorage.removeItem('user')
}
const authService = {
register, logout, login
}
export default authService
authSlice.js
import { createSlice, createAsyncThunk } from '#reduxjs/toolkit'
import authService from './authService'
// Get user from localStorage
const user = JSON.parse(localStorage.getItem('user'))
const initialState = {
user: user ? user : null,
isError: false,
isSuccess: false,
isLoading: false,
message: ""
}
// Register user
export const register = createAsyncThunk('auth/register', async (user, thunkAPI) => {
try {
return await authService.register(user)
} catch (error) {
const message = (error.response && error.response.data && error.response.data.message) || error.message || error.toString()
return thunkAPI.rejectWithValue(message)
}
})
// Login user
export const login = createAsyncThunk('auth/login', async (user, thunkAPI) => {
try {
return await authService.login(user)
} catch (error) {
const message = (error.response && error.response.data && error.response.data.message) || error.message || error.toString()
return thunkAPI.rejectWithValue(message)
}
})
// logout
export const logout = createAsyncThunk('auth/logout' , async () => {
await authService.logout()
})
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
reset: (state) => {
state.isLoading = false
state.isSuccess = false
state.isError = false
state.message = ''
}
},
extraReducers: (builder) => {
builder
.addCase(register.pending, (state) => {
state.isLoading = true
} )
.addCase(register.fulfilled, (state, action) => {
state.isLoading = false
state.isSuccess = true
state.user = action.payload
})
.addCase(register.rejected, (state, action) =>{
state.isLoading = false
state.isError = true
state.message = action.payload
state.user = null
})
.addCase(login.pending, (state) => {
state.isLoading = true
} )
.addCase(login.fulfilled, (state, action) => {
state.isLoading = false
state.isSuccess = true
state.user = action.payload
})
.addCase(login.rejected, (state, action) =>{
state.isLoading = false
state.isError = true
state.message = action.payload
state.user = null
})
.addCase(logout.fulfilled, (state) =>{
state.user = null
})
}
})
export const { reset } = authSlice.actions
export default authSlice.reducer
Look at this property access:
thunkAPI.getState().auth.user.token
You are trying to access the auth user's token.
But your initial state looks like this:
const initialState = {
user: user ? user : null,
isError: false,
isSuccess: false,
isLoading: false,
message: ""
}
In the case that the user doesn't exist, how can you access their token?
When you are calling reset(), your user is probably being set to null, hence the error only appears at that point.
You should check that the user is not null before accessing the token, and handle the case where it is null however you want.
if (thunkAPI.getState().auth.user) {
// only in the case the above condition is true,
// then you can access the token.
}

Live updating data in React-native from Firebase(with NestJs)

I'm working learning React Native/Reactjs with NodeJs(NestJs) and Firebase. I have some problems with updating live data. For example, I have and bell icon which represent Notification and I want it to update whenever the data change and show the number of unread noti in database. My code:
API
async getNotifications(data: any): Promise<any> {
const receiverId = data.userId;
const warehouseId = await this.getKhoId(receiverId);
const ref = db.ref('/Notification');
const result = [];
await ref.once('value', function (snapshot) {
if (snapshot.val())
for (let j = 0; j < warehouseId.length; j++)
for (let i = 0; i < snapshot.val().length; i++) {
if (
snapshot.val()[i] &&
snapshot.val()[i].warehouseId == warehouseId[j]
) {
result.push({
content: snapshot.val()[i].content,
read: snapshot.val()[i].read,
time: snapshot.val()[i].time,
number: i,
});
}
}
else return 'None';
});
return result;
}
React Native
useEffect(() => {
const handleData = async () => {
const userId = await SecureStore.getItemAsync("userId");
const numberOfNoti = await axios({
method: "post",
url: "http://192.168.1.8:5000/getNotifications",
data: {
userId: userId,
},
}).then(function (response) {
let val = 0;
if (response.data) {
response.data.forEach((item) => {
if (item.read === 0) {
val++;
}
});
}
return val;
});
setNumberOfNoti(numberOfNoti);
};
handleData();
}, []);
and the component AppBar contain the bell icon:
{numberOfNoti !== 0 ? (
<Badge size={16} style={{ position: "absolute", top: 5, right: 5 }}>
{numberOfNoti}
</Badge>
) : (
void 0
)}
How can I live updating the number in Badge when data in Firebase change? I also have Notification component which contains a list of Notification and updating state of that Notification(from unread to read onPress) and I want to change the Badge number too.
I realize I can call API to update continuously using setInterval and it looks something like this. I don't know whether it's a proper way or not but it run fine.
useEffect(() => {
const interval = setInterval(() => {
const handleData = async () => {
const userId = await SecureStore.getItemAsync("userId");
const numberOfNoti = await axios({
method: "post",
url: "http://192.168.1.2:5000/getNotifications",
data: {
userId: userId,
},
}).then(function (response) {
let val = 0;
if (response.data) {
response.data.forEach((item) => {
if (item.read === 0) {
val++;
}
});
}
return val;
});
setNumberOfNoti(numberOfNoti);
};
handleData();
}, 1000);
return () => clearInterval(interval);
}, []);

How to receive re-requested data when data requested by mounted() is re-requested by aixos interceptor

the code below is the first request for get list data
mounted() {
this.getList()
},
methods: {
handleClick(row) {
console.log(row.id)
console.log(row.url)
this.$router.push({ name: 'Main', query: { id: row.id } })
},
getList() {
axios
.get('/api/v1/requests/all', {
params: {
userId: this.$store.state.userInfo.id,
},
})
.then(response => {
let moment = require('moment')
for (var item of response.data.data) {
item.createdAt = moment(item.createdAt).format(
'YYYY-MM-DD HH:mm:ss',
)
}
this.items = response.data.data
})
.catch(error => {
console.log(error)
})
}
my interceptor
axios.interceptors.response.use(
function (response) {
return response
},
async function (error) {
const originalRequest = error.config
if (error.response.status === 401 && !originalRequest._retry) {
error.response.config._retry = true
sessionStorage.removeItem('access-token')
let headers = {
grant_type: 'refresh_token',
Authorization: sessionStorage.getItem('refresh-token'),
}
axios
.post('/api/v1/users/refresh_token', {}, { headers: headers })
.then(response => {
let token = response.data.data
sessionStorage.setItem('access-token', token)
originalRequest.headers['Authorization'] = token
originalRequest.headers['grant_type'] = 'grant_type'
return axios.request(originalRequest)
})
.catch(error => {
console.log(error)
alert('blablabla.')
})
}
return Promise.reject(error)
},
)
the flow is i understand
1.token expired
2.move to list page
3.mounted hook is request data
4.getList -> axios get('~~request/all')
5.interceptor->axios post('~~~refresh_token')
6.re request with new token(request/all)
7.re request is 200, but not update list page
i'd really appreciate your help :)
Seems like you need to return the second request (await for result and return). Right now the result of second request seems to be ignored
axios.interceptors.response.use(
function (response) {
return response;
},
async function (error) {
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
error.response.config._retry = true;
sessionStorage.removeItem("access-token");
let headers = {
grant_type: "refresh_token",
Authorization: sessionStorage.getItem("refresh-token"),
};
const [secondError, res] = await axios // await here
.post("/api/v1/users/refresh_token", {}, { headers: headers })
.then(async (response) => {
let token = response.data.data;
sessionStorage.setItem("access-token", token);
originalRequest.headers["Authorization"] = token;
originalRequest.headers["grant_type"] = "grant_type";
return [null, await axios.request(originalRequest)];
})
.catch((err) => {
console.log(err);
alert("blablabla.");
return [err, null];
});
// Handle here
if(secondError) {
return Promise.reject(secondError);
}
return Promise.resolve(res)
}
return Promise.reject(error);
}
);
The above solution worked for me perfectly. here's the modified code that I used for my requirement.
export default function axiosInterceptor() {
//Add a response interceptor
axios.interceptors.response.use(
(res) => {
// Add configurations here
return res;
},
async function (error) {
const originalRequest = error.config;
let secondError, res
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
[secondError, res] = await axios({
method: "POST",
url: `${baseURL}/account/token/refreshtoken`,
withCredentials: true,
headers: { "Content-Type": "application/json" },
})
.then(async (response) => {
//handle success
return [null, await axios.request(originalRequest)];
}).catch(function (error) {
console.error(error)
});
}
if (secondError) {
return Promise.reject(secondError);
}
return Promise.resolve(res)
}
);
}

Unit testing S3 getObject with aws-sdk-mock issue on unit test

I am writing a unit test for S3 getObject. I used aws-sdk-mock, but when I run it I get an issue.
Error: the object {
"error": "InvalidAccessKeyId: The AWS Access Key Id you provided does not exist in our records."
"status": false
} was thrown, throw an Error :)
Here is the Unit test which I am writing:
const { expect } = require( 'chai' );
const utils = require( './s3Utils' );
const AWS = require( 'aws-sdk' );
const awsMock = require( 'aws-sdk-mock' );
const fs = require( 'fs' );
awsMock.setSDKInstance( AWS );
describe( 'S3 Utils', () => {
before(() => {
const rootPath = process.cwd();
awsMock.mock( 'S3', 'getObject', Buffer.from( fs.readFileSync( `${ rootPath }/file.js` )));
});
after(() => {
awsMock.restore( 'S3' );
});
it( 'Get the object from S3', async () => {
const result = await utils.getFilesFromS3( '/somepath' );
expect( result ).to.have.ownProperty( 'status' );
});
});
Here is the function for which I am writing the unit test:
const { s3Handler, BUCKET } = require( './../../config/s3Config' );
exports.getFilesFromS3 =
( bucketPath, fileName = 'index.js', bucketName = BUCKET ) => new Promise(( resolve, reject ) => {
try {
const params = { Key: `${ bucketPath }/${ fileName }`, Bucket: bucketName };
s3Handler.getObject( params, ( error, data ) => {
if ( error ) {
reject({ status: false, error });
} else {
if (( data !== undefined || data !== null ) && Object.prototype.hasOwnProperty.call( data, 'Body' )) {
const contents = data.Body.toString( 'utf-8' );
resolve({ status: true, contents });
}
reject({ status: false, error: `No body present ${ bucketPath }/${ fileName }` });
}
});
} catch ( error ) {
reject({ status: false, error });
}
});
What am I missing here?
This will work
const getObjectStub = AWS.S3.prototype.getObject = Sinon.stub();
getObjectStub.yields(null, {
AcceptRanges: "bytes",
ContentLength: 3191,
ContentType: "image/jpeg",
Metadata: {
},
TagCount: 2,
VersionId: "null"
}
);

Resources