How to get data from BigQuery in React.js app? - node.js

What I want to do and the problem
I want to access a table in the BigQuery, but got error like
TypeError: fs.createReadStream is not a function
at GoogleAuth.getClient (googleauth.js:497)
at GoogleAuth.authorizeRequest (googleauth.js:530)
at BigQuery.makeAuthenticatedRequest (util.js:374)
at BigQuery.request_ (service.js:129)
at BigQuery.request (service.js:140)
at BigQuery.createJob (bigquery.js:942)
at BigQuery.wrapper (index.js:42)
at BigQuery.createQueryJob (bigquery.js:862)
at BigQuery.wrapper (index.js:42)
at BigQuery.query (bigquery.js:1264)
at index.js:69
at new Promise (<anonymous>)
at BigQuery.wrapper (index.js:54)
at Signup.handleClick (Signup.js:52)
at HTMLUnknownElement.callCallback (react-dom.development.js:336)
at Object.invokeGuardedCallbackDev (react-dom.development.js:385)
at invokeGuardedCallback (react-dom.development.js:440)
at invokeGuardedCallbackAndCatchFirstError (react-dom.development.js:454)
at executeDispatch (react-dom.development.js:584)
at executeDispatchesInOrder (react-dom.development.js:609)
at executeDispatchesAndRelease (react-dom.development.js:713)
at executeDispatchesAndReleaseTopLevel (react-dom.development.js:722)
at forEachAccumulated (react-dom.development.js:694)
at runEventsInBatch (react-dom.development.js:739)
at runExtractedPluginEventsInBatch (react-dom.development.js:880)
at handleTopLevel (react-dom.development.js:5803)
at batchedEventUpdates$1 (react-dom.development.js:24401)
at batchedEventUpdates (react-dom.development.js:1415)
at dispatchEventForPluginEventSystem (react-dom.development.js:5894)
at attemptToDispatchEvent (react-dom.development.js:6010)
at dispatchEvent (react-dom.development.js:5914)
at unstable_runWithPriority (scheduler.development.js:697)
at runWithPriority$2 (react-dom.development.js:12149)
at discreteUpdates$1 (react-dom.development.js:24417)
at discreteUpdates (react-dom.development.js:1438)
at dispatchDiscreteEvent (react-dom.development.js:5881)
My Codes
First, I want to check the code with simple code. There is a button and when clicked it, the handleClick function works. All element for access BigQuery are in this function for now.
import React from 'react';
import Avatar from '#material-ui/core/Avatar';
import Button from '#material-ui/core/Button';
import CssBaseline from '#material-ui/core/CssBaseline';
import PersonIcon from '#material-ui/icons/Person';
import Typography from '#material-ui/core/Typography';
import Container from '#material-ui/core/Container';
class Signup extends React.Component {
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
const { BigQuery } = require('#google-cloud/bigquery');
const bigquery = new BigQuery({
projectId: '(PROJECT_ID)',
keyFilename: '../../credentials/(credential file name).json',
});
const query = `
SELECT *
FROM \`(PROJECT_ID).paper_list.user_auth_info\`;
`
bigquery.query(query)
.then(data => {
const rows = data[0];
rows.forEach(row => alert("Hello"));
})
.catch(err => console.log(err));
}
render() {
const { classes } = this.props;
return (
<Container
component="main"
maxWidth="xs"
className={classes.outer}
>
<CssBaseline />
<div className={classes.paper}>
<Avatar className={classes.avatar}>
<PersonIcon />
</Avatar>
<Typography component="h1" variant="h5">
Sign Up
</Typography>
<form className={classes.form} noValidate>
<Button
fullWidth
variant="contained"
color="primary"
className={classes.submit}
onClick={this.handleClick}
>
Sign Up
</Button>
</form>
</div>
</Container>
);
}
}
The directory structure is like following,
.
├── Dockerfile
├── README.md
├── app.yaml
├── credentials # <- credential file is in this directory
├── node_modules
├── package-lock.json
├── package.json
├── public
└── src
├── App.css
├── App.js
├── App.test.js
├── Main.js
├── components
│   ├── AddFile.js
│   ├── Footer.js
│   ├── Header.js
│   ├── Inner.js
│   ├── Login.js
│   ├── PaperFolder.js
│   ├── PaperInfo.js
│   ├── PaperLabels.js
│   ├── SearchResultTable.js
│   ├── SideBar.js
│   ├── Signup.js # <- the code above
│   ├── TopLinks.js
│   └── ToppageMain.js
├── images
│   └── maarten-van-den-heuvel-8EzNkvLQosk-unsplash.jpg
├── index.css
├── index.js
├── serviceWorker.js
How to fix this error?

Thanks to the comment by Blundering Philosopher, I could understand the problem.
The BigQuery should be accessed from server-side, but the React.js is front-end, this was the problem. I wrote the API server with Go, and resolved it.

Related

Generating uuid v5 in node.js erros out with no information?

I am using this npm package:
https://www.npmjs.com/package/uuid
I want to egenrate a v5 uuid.
I can generate a v4 no problem by requiring the module:
const { v4: uuidv4 } = require('uuid');
and then running:
console.log(`uuidv4: ${uuidv4()}`);
So then I try to generate a v5:
const { v5: uuidV5 } = require('uuid');
const MY_NAMESPACE = 'f709b20b-3353-4c32-8df9-66bc48e91ea9';
var v5uuid = uuidV5('hello', MY_NAMESPACE);
console.log(`userUUID: ${v5uuid}`);
However, the app gets to line var v5uuid = uuidV5('hello', MY_NAMESPACE); and then goes straight to the catch error. In the variables error says:
'uuidV5 is not a function'
running npm ls uuid:
├─┬ nodemon#1.3.3
│ └─┬ update-notifier#0.1.10
│ └─┬ configstore#0.3.2
│ └── uuid#2.0.3
├─┬ request#2.88.2
│ └── uuid#3.3.2 deduped
├─┬ sequelize#6.14.1
│ └── uuid#8.3.2
└── uuid#3.3.2
What am I doing wrong?
Below solution worked for me!
If your using package.json, add the following to package.json
{
"type": "module"
...
}
Now use can use import with node js
// index.js
import { v5 as uuidv5 } from "uuid";
const MY_NAMESPACE = "1b671a64-40d5-491e-99b0-da01ff1f3341";
uuidv5("Hello World", MY_NAMESPACE); // ⇨ 'a572fa0f-9bfa-5103-9882-16394770ad11'
Check your output using
node index.js

How to import all express router files from multiple directories in nodejs?

I'm building a REST API with versioning support. Here is my directory structure.
.
├── src
│ ├── api
│ │ ├── v1
│ │ │ ├── modules ─ ...
│ │ │ ├── routers
│ │ │ │ ├─── auth.router.js
│ │ │ │ ├─── posts.router.js
│ │ ├── v2
│ │ │ ├── modules ─ ...
│ │ │ ├── routers ─ ...
├── app.js
I want the router files imported to app.js. I've looked for the solution for hours but all I found is how to import each file manually through app.use(). This is doable but as the version numbers and router files keep increasing, this can lead to redundant work. I need a way to import these files with the least manual lines of code possible.
It is not possible to directly do this with Express, generally people mange modules manually with NodeJS, as it doesn't take a lot of work to do at all. In terms of version numbers, you could specify a version setting or constant somwhere, and import depending on that number.
For instance:
// routes.js
const apiVersion = "v2";
module.exports = {
require(`./${apiVersion}/auth.route`),
}
If this is not ideal, one hacky way to manage this is by grabbing all of the route files with the fs module, and importing them automatically. This is quite a hacky way of doing it, but I came up with something like this:
// router.js
const fs = require("fs/promises");
const { Router } = require("express");
const router = Router();
const apiVersion = "v2";
const loadRoutes = async () => {
// grab all the route files from a directory using fs
// use require to grab them from the source files
}
const routes = loadRoutes();
routes.forEach(route => {
router.use(route);
})
// app.js
const router = require("./path/to/router");
// ...boilerplate
app.use(router);

How to get the path to a file outside the root folder in React application

This is simplified folder structure in my React application created with the create-react-app. For the back-end I'm using the Express framework.
└── ReactApp/
├── client/
| ├── node_modules/
| ├── public/
| └── src/
| └── components/
| └── component.js
└── server/
├── index.js
└── Uploads/
└── file.txt
Inside component.js file I want to define the path to the file.txt file located to the server/Uploads folder.
handleClick() {
const pathToFile = '../../server/Uploads/file.txt;
this.setState({ input: pathToFile})
}
The issue is that this defined path cannot locate the txt file inside the Uploads folder.
Try:
handleClick() {
const pathToFile = '../../../server/Uploads/file.txt';
this.setState({ input: pathToFile})
}
The solution is to configure ExpressJS to serve static files inside the Uploads folder.
index.js
app.use(express.static('Uploads'));
and then change the path inside the component.js file.
handleClick() {
const pathToFile = 'file.txt';
this.setState({ input: pathToFile})
}

AWS SAM Nested Application in Python with Dynamorm

I am using AWS SAM to build a Serverless application. I followed the instruction to build a nested application.
My application structure is basically the following:
.
├── MAKEFILE
├── README.md
├── __init__.py
├── apps
│ ├── __init__.py
│ ├── account
│ │ ├── __init__.py
│ │ ├── endpoints.py
│ │ ├── models.py
│ │ ├── requirements.txt
│ │ └── template.yaml
├── samconfig.toml
└── template.yaml
The requirements.txt in the folder apps/account/ has the following python packages: boto3 marshmallow and dynamorm.
The sam build and sam deploy works fine and the lambda functions are deployed correctly. However, I receive an error when calling the lambda function. The logs show the following error Unable to import module 'endpoints': No module named 'dynamorm'.
Here are excerpts from my code:
endpoints.py
import json
import boto3
from models import Account
print('Loading function')
def account_info(event, context):
apiKey = event["requestContext"]["identity"]["apiKeyId"]
account_info = Account.get(id= apiKey)
return {
"statusCode": 200,
"body": json.dumps(account_info)
}
models.py
import datetime
from dynamorm import DynaModel, GlobalIndex, ProjectAll
from marshmallow import Schema, fields, validate, validates, ValidationError
class Account(DynaModel):
# Define our DynamoDB properties
class Table:
name = 'XXXXXXXXXX'
hash_key = 'id'
read = 10
write = 5
class Schema:
id = fields.String(required=True)
name = fields.String()
email = fields.String()
phonenumber = fields.String()
status = fields.String()
I am not sure what am I missing? Are there additional instructions to build a nested app in SAM?
Thank you so much for the help!
According to https://github.com/awslabs/aws-sam-cli/issues/1213, this feature is not supported yet.
In my case, I did 'sam build' on every nested stacks and fix parent yaml template as following (use template.yaml generated by sam build command), then works. But just workaround and not nice way.
XXX_APP:
Type: AWS::Serverless::Application
Properties:
Location: nest_application/.aws-sam/build/template.yaml

Reference module from a module in separate Terraform projects

Is it possible with Terraform to have a directory structure like the following:
├── environments
│   └── production
│   ├── app1
│   ├── instances.tf
│   ├── app2
│   └── shared
│   ├── iam.tf
│   └── security_groups.tf
└── modules
└── iam
└── node
Where environments/production/{app1, app2, shared} all each have their own terraform state and each are independent of each other. However, from app1 and app2 I need to reference module output variables like security groups, IAM etc from shared.
So environments/production/shared/iam.tf looks like:
module "iam" {
source = "../../../modules/iam"
var1 = "foo"
var2 = "bar"
var3 = "car"
var4 = "nar"
}
How then, from app1, or app2 do I reference the instance of iam from shared?
environments/production/app1/instances.tf:
module "app1" {
source = "../../../modules/node"
iam_profile_id = { how do I reference the IAM module from shared here?
// shared.module.iam.profile_id?
}

Resources