I am currently working on a React-app front-end for Amazon AWS S3. The goal of the project is to allow a user to upload multiple images to a S3 bucket, and then call a Lambda function to send the uploaded images to Amazon Rekognition for labeling. The results will then be returned in a CSV file that the user can download as the output.
However, I am currently encountering an issue where I am getting the following error message:
Failed to compile.
export 'downloadCSV' (reexported as 'downloadCSV') was not found in './rekognitionActions' (possible exports: addFacesToCollection, createCollection, detectLabels, getLabeledResults, handleFileUpload, indexFaces, parseCSV, searchFaces, searchFacesByImage, uploadImages, uploadImagesAndGetLabels)
ERROR in ./src/components/actions/index.js 5:0-84
export 'downloadCSV' (reexported as 'downloadCSV') was not found in './rekognitionActions' (possible exports: addFacesToCollection, createCollection, detectLabels, getLabeledResults, handleFileUpload, indexFaces, parseCSV, searchFaces, searchFacesByImage, uploadImages, uploadImagesAndGetLabels)
ERROR in ./src/components/actions/rekognitionActions.js 4:0-38
Module not found: Error: Can't resolve 'fs' in 'C:\Users\luisj\Desktop\awsapp\awsapp\src\components\actions'
I am also receiving
Module not found: Error: Can't resolve 'fs' in 'C:\Users\luisj\Desktop\awsapp\awsapp\src\components\actions'
I am unsure of what is causing this issue and would greatly appreciate any help in resolving it.
rekognitionActions.js
import AWS from 'aws-sdk';
import { createReadStream } from 'fs';
import Papa from 'papaparse';
const rekognition = new AWS.Rekognition({
accessKeyId: process.env.REACT_APP_AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.REACT_APP_AWS_SECRET_ACCESS_KEY,
});
const s3 = new AWS.S3({
accessKeyId: process.env.REACT_APP_AWS_ACCESS_KEY_ID,
secretAccessKey: process.env.REACT_APP_AWS_SECRET_ACCESS_KEY,
});
export const detectLabels = async (image) => {
const params = {
Image: {
S3Object: {
Bucket: process.env.REACT_APP_AWS_S3_BUCKET,
Name: image,
},
},
MaxLabels: 10,
MinConfidence: 80,
};
const data = await rekognition.detectLabels(params).promise();
return data.Labels;
};
export const createCollection = async (collectionId) => {
const params = {
CollectionId: collectionId,
};
await rekognition.createCollection(params).promise();
};
export const indexFaces = async (collectionId, image) => {
const params = {
CollectionId: collectionId,
Image: {
S3Object: {
Bucket: process.env.REACT_APP_AWS_S3_BUCKET,
Name: image,
},
},
};
const data = await rekognition.indexFaces(params).promise();
return data.FaceRecords;
};
export const searchFacesByImage = async (collectionId, image) => {
const params = {
CollectionId: collectionId,
Image: {
S3Object: {
Bucket: process.env.REACT_APP_AWS_S3_BUCKET,
Name: image,
},
},
MaxFaces: 10,
FaceMatchThreshold: 80,
};
const data = await rekognition.searchFacesByImage(params).promise();
return data.FaceMatches;
};
export const uploadImages = async (images) => {
const uploadPromises = images.map(async (image) => {
const params = {
Bucket: process.env.REACT_APP_AWS_S3_BUCKET,
Key: image.name,
Body: image,
};
await s3.upload(params).promise();
});
await Promise.all(uploadPromises);
};
export const getLabeledResults = async (images) => {
const labelPromises = images.map(async (image) => {
const labels = await detectLabels(image.name);
return { imageName: image.name, labels };
});
const labeledResults = await Promise.all(labelPromises);
return labeledResults;
};
export const uploadImagesAndGetLabels = async (images) => {
await uploadImages(images);
const labeledResults = await getLabeledResults(images);
return labeledResults;
};
export const parseCSV = async (file) => {
return new Promise((resolve, reject) => {
Papa.parse(createReadStream(file), {
header: true,
complete: (results) => {
resolve(results.data);
},
error: (error) => {
reject(error);
},
});
});
};
export const addFacesToCollection = async (collectionId, images) => {
const indexFacePromises = images.map(async (image) => {
const indexedFaces = await indexFaces(collectionId, image.name);
return { imageName: image.name, indexedFaces };
});
const indexedResults = await Promise.all(indexFacePromises);
return indexedResults;
};
export const searchFaces = async (collectionId, images) => {
const searchFacePromises = images.map(async (image) => {
const faceMatches = await searchFacesByImage(collectionId, image.name);
return { imageName: image.name, faceMatches };
});
const searchResults = await Promise.all(searchFacePromises);
return searchResults;
};
export const handleFileUpload = async (file, collectionId) => {
try {
const images = await parseCSV(file);
await uploadImagesAndGetLabels(images);
await createCollection(collectionId);
const indexedResults = await addFacesToCollection(collectionId, images);
const searchResults = await searchFaces(collectionId, images);
return { indexedResults, searchResults };
} catch (error) {
throw error;
}
};
index.js
import * as rekognitionActions from './rekognitionActions';
import * as otherActions from './otherActions';
import { uploadImages, getLabeledResults, downloadCSV } from './actions';
export const { uploadImages, getLabeledResults, downloadCSV } = rekognitionActions;
export const { otherAction1, otherAction2 } = otherActions;
I have made my full project available on my GitHub repository, which can be accessed HERE
I am trying to create a React-app front-end for Amazon AWS S3. The goal of this project is to allow a user to upload multiple images to a S3 bucket, and then call a lambda function to send the uploaded images to Amazon Rekognition for labeling. The results are then returned in a CSV file that the user can download as the output.
I have created the necessary components and actions for this project, but when I try to compile the code, I am getting an error :
Module not found: Error: Can't resolve './components/actions' in 'C:\Users\luisj\Desktop\awsapp\awsapp\src\components'". I am also getting an error that says "export 'downloadCSV' (reexported as 'downloadCSV') was not found in './rekognitionActions' (possible exports: addFacesToCollection, createCollection, detectLabels, getLabeledResults, handleFileUpload, indexFaces, parseCSV, searchFaces, searchFacesByImage, uploadImages, uploadImagesAndGetLabels)". Additionally, there is an error that says "Module not found: Error: Can't resolve 'fs' in 'C:\Users\luisj\Desktop\awsapp\awsapp\src\components\actions'
I was expecting the code to compile without any errors, and for the application to function as intended. However, the errors I am receiving are preventing me from moving forward with the project.
I have tried re-organizing the file structure, double checking the imports and exports in the code, and making sure that all necessary dependencies are installed, but I am still encountering these errors.
This is my code for /+layout.ts
export const ssr = false;
export const load = (async ({ url }) => {
let user: null | { user: User, player: SupaPlayer } = await supa.getUser((event, session) => {
...
});
if (user !== null) {
...
return { ...user, contestants: await supa.getContestants() };
} else {
if (!url.pathname.includes('/login')) {
// I AM REACHING THIS POINT
throw redirect(301, "/login");
}
// return null;
}
}) satisfies LayoutLoad
I am trying this with a route that does not exist (i.e. there is nothing in /routes) and get two errors:
in the terminal that I am running my code for dev I get Error: Not found: /<route> and a stacktrace - indeed the route does not exist in my code but I would expect Sveltekit not to create errors for that
in the browser, I get error: Not found: /<route> attributed to manifest.js, and, more importantly, the redirect to /login is not working, and I get Uncaught (in promise) Redirect {status: 301, location: '/login'}
I suspect the initial errors are causing the redirect to fail, as it does work for known routes.
The error seems to originate from manifest.js, which reads as below and which has no obvious default handler for an unknown route
export { matchers } from '/.svelte-kit/generated/client/matchers.js';
export const nodes = [() => import("/.svelte-kit/generated/client/nodes/0.js"),
() => import("/.svelte-kit/generated/client/nodes/1.js"),
...];
export const server_loads = [];
export const dictionary = {
"/": [2],
...
};
export const hooks = {
handleError: (({ error }) => { console.error(error) }),
};
As it is said here React docs, on uncaught errors the whole tree will unmount.
Query 1:
const { data: post } = useQuery<PostResponseDto, AxiosError>(
['fetch-post', params],
() => fetchPost(params!.postId),
{
refetchOnMount: true,
onError: (err) => {
// do something with the error
},
},
);
Query 2:
const {
data: postCommentsGroups,
fetchNextPage,
isFetchingNextPage,
hasNextPage,
refetch,
} = useInfiniteQuery<PostCommentsResponseDto, AxiosError>(
['fetch-post-comments', params],
({ pageParam = 0 }) => fetchPostComments(params!.postId, pageParam),
{
refetchOnMount: true,
getNextPageParam: (lastPage) => {
if (!lastPage.data.nextPage) {
return false;
} else {
return lastPage.data.nextPage;
}
},
onError: (err) => {
// do something with the error
},
},
);
Fetch functions:
export const fetchPost = async (webId: string) => {
const response = await axiosInstance.get(`${API_URL}/post/${webId}`);
return response.data;
};
export const fetchPostComments = async (webId: string, page: number) => {
const response = await axiosInstance.get(
`${API_URL}/post/${webId}/comments?page=${page}&limit=${COMMENTS_LIMIT}`,
);
return response.data;
};
The problem: When these queries result in status code !== 200, uncaught errors appear in the console (see below) and the whole React tree unmounts. This definitely is not the behavior I want. E.g. on both of these queries I get 404 if postId is incorrect and when this happens I want to do certain actions in onError callback (show some info to the user), but this impossible due to the uncaught errors by react-query and React unmounting the whole tree.
This is one of the few uncaught errors (AxiosErrors).
Why is this happening?
P.S.: I don't think this happens with useMutate() hook.
P.P.S: I am using global ErrorBoundary but that is irrelevant for this problem. I want to manipulate the DOM in that specific component in which queries are being made/errored.
I'm new into using files with .spec.js suffix to test files with Jest, so hope it's not a stupid question. I didn't found anything through Google + Stackoverflow research.
I would like to check an if else condition containing a new window.location using jest.
Here is my file.ts
export const loadBSection = (bSectionId: string) => async (
dispatch: Dispatch,
getState: GetState,
{ bSectionApi }: Deps,
) => {
try {
...
} catch (e) {
dispatch(setBSectionErrorMessage(e.message));
if (e.response.status === 404) {
window.location.href = '/page-not-found.html';
}
}
};
My file.spec.ts
it('should .. and forward to a 404 page', async () => {
...
expect(store.getActions()).toEqual([setBSectionLoading(true), setBSectionErrorMessage(errorMessage)]);
// TODO what is expected here?
});
Do you have any ideas?
As I'm new to this, maybe you have some sources for deep dives?
I used: https://create-react-app.dev/docs/running-tests/ as an intro.
Do you have other resources which are helpful to find some documentation in the future?
An idea I had but not sure if it works
Object.defineProperty(window.location, 'href', {
writable: true,
value: '/page-not-found.html',
});
It's solved!
So it was useful to set response optional so that other errors get catched as well. Furthermore it's easier to mock functions, so I changed window.location.href to window.location.assign(url).
Makes the same but easier for testing.
file.ts
catch (e) {
dispatch(setBSectionErrorMessage(e.message));
if (e.response?.status === 404) {
window.location.assign('/page-not-found.html');
}
}
file.spec.ts
I'm creating error and errorMessage inside of the test method. Here you can see how an error object can be assembled with a status code as a response:
it('should navigate to /page-not-found.html ...', async () => {
const bSectionIdMock = '123';
const error = Object.assign((new Error(), { response: { status: 404 } }));
bSectionApi.bSectionsBSectionIdGet.mockRejectedValue(error);
window.location.assign = jest.fn();
await store.dispatch(loadBSection(bSectionIdMock));
expect(window.location.assign).toHaveBeenCalledWith('/page-not-found.html');
});
I have a question about a project deployment with NextJS/Vercel.
According to documentation, await fetch is supporting only absolute URLs. Example:
export async function getStaticProps(context) {
const route = process.env.APIpath + 'api/category/getCategories';
const res = await fetch(route)
const json = await res.json()
return {
props: {
data: json,
},
};
}
where APIpath: 'http://localhost:3000/',
Question: How can I deploy a project on vercel.com/test/my_project? because when I only change process.env.APIpath to vercel.com/test/my_project = error.
P.S. Error message
Build error occurred
Error: Export encountered errors on following paths:
categories/database/categoryList - the page I am calling getStaticProps(context) above