Shopify API Node/Express Cannot read properties of undefined (reading 'Rest') - node.js

Just starting off with Shopify, and trying to get an order. Following the Shopify API documentation, here is my code:
const Shopify = require('#shopify/shopify-api');
const client = new Shopify.Clients.Rest('my-store.myshopify.com',
process.env.SHOPIFY_KEY);
module.exports.getShopifyOrderById = async (orderId) => {
return await client.get({
path: `orders/${orderId}`,
});
}
I get the following error when I execute this code:
TypeError: Cannot read properties of undefined (reading 'Rest')
Can't seem to figure out what the issue is.

You need to use Object destructing to get the Shopify object or use default export like below.
const { Shopify } = require('#shopify/shopify-api');
const client = new Shopify.Clients.Rest('my-store.myshopify.com',
process.env.SHOPIFY_KEY);
OR
const Shopify = require('#shopify/shopify-api').default;
const client = new Shopify.Clients.Rest('my-store.myshopify.com',
process.env.SHOPIFY_KEY);
OR
const ShopifyLib = require('#shopify/shopify-api');
const client = new ShopifyLib.Shopify.Clients.Rest('my-store.myshopify.com',
process.env.SHOPIFY_KEY);
This has to do with how ES6 modules are emulated in CommonJS and how you import the module. You can read about that here.

Related

How to use dynamic require in Remix?

In a Remix action, I use a dynamic require to retrieve different JSON files:
export async function action({ request }: { request: Request }) {
const body = await request.formData();
const country = body.get("country");
const cities = require(`~/cities_by_country/${country}.json`);
return cities;
}
This produces and "Application Error": Error: Cannot find module '~/cities_by_country/Afghanistan.json'
It turns out that the dynamic require is the issue. Hardcoding the country like this works:
const cities = require(`~/cities_by_country/Afghanistan.json`);
I read that adding "module": esnext (or es2020 or es2022) to tsconfig.json would enable dynamic imports, at least for React. I tried it but got the same results.
I've read these docs as well to no avail:
asset url imports
data-loading
resource routes
What am I missing?

Firebase getAuth() throws error getProvider of undefined but can access database

I have the following code running on a Node server.
import admin from 'firebase-admin';
import {getAuth} from 'firebase/auth';
class MyFirebase {
constructor() {
console.log("MyFirebase Constructor");
this.firebaseApp = admin.initializeApp({
credential: admin.credential.cert("PATH_TO_CERT/cert.json"),
databaseURL: "https://DATABASE_URL",
});
console.log("App name="+firebaseApp.name);
this.defaultAuth = getAuth(firebaseApp);
this.database = this.firebaseApp.database();
// database ref code here...
}
}
and it throws the following error:
return app.container.getProvider(name);
TypeError: Cannot read property 'getProvider' of undefined
If I remove "firebaseApp" from the getAuth(..) call I get this error:
No Firebase app '[DEFAULT'] has been created - call Firebase
App.initializeApp() (app/no-app)
However the "console.log("App Name...")" line produces:
App name=[DEFAULT]
So clearly a DEFAULT app has been created. Additionally if I remove the "getAuth..." call the database calls pulling data from the realtime database below it work just fine, which seem to imply the authentication worked properly because I can access data from the database.
What the heck is going on?
You are confusing Firebase Admin SDK (Node.js) with Firebase Javascript SDK. The former is for the back-end, while the latter is for the front-end. I understand your confusion because the front-end package/s are installable via NPM, although they are meant to be bundled with front-end code.
You can't do this:
import admin from 'firebase-admin' // back-end code
import { getAuth } from 'firebase/auth' // front-end code !!!
const adminApp = admin.initializeApp(...)
getAuth(adminApp) // TypeScript actually catches this error
/*
Argument of type 'App' is not assignable to parameter of type 'FirebaseApp'.
Property 'automaticDataCollectionEnabled' is missing in type 'App' but required in type 'FirebaseApp'.ts(2345)
app-public.d.ts(92, 5): 'automaticDataCollectionEnabled' is declared here.
const adminApp: admin.app.App
*/
If you are on the back-end, just use adminApp.auth() to get the Auth instance. If on the front-end, you need to call getAuth with the front-end Firebase App instance:
import { initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
const app = initializeApp(...)
const auth = getAuth(app)
The new modular apis have a slightly different syntax. The following should still work if you wrap it in a class, but as long as you only do this once at the top of your express? server you shouldn't need to use a class.
Also, I'm using the require syntax but imports should work too depending on your setup.
//Import each function from the correct module.
const { initializeApp, applicationDefault } = require("firebase-admin/app");
const { getAuth } = require("firebase-admin/auth");
const { getDatabase } = require("firebase-admin/database");
const app = initializeApp({
credential: applicationDefault(), //Don't forget to export your configuration json https://firebase.google.com/docs/admin/setup
databaseURL: "https://DATABASE_URL",
});
const auth = getAuth(app)
const database = getDatabase(app)
It's not super well documented but you can find hints in the Admin SDK reference: https://firebase.google.com/docs/reference/admin/node/firebase-admin.auth
One tip: In VSCode you should see the a description of each function when you hover over them, if you have the import path formatted correctly.

Dynamic file names in react native require()

We're working on an app that will allow users to store templates with images on them, and pull those templates up later. This is for an AR environment using Viro on React Native.
We're trying to dynamically load an image into the component, and receiving errors when we require the filepath, which has been set to a variable:
const exampleUri = '/some/uri'
render() {
return(
<Viro3DObject
source={require(exampleUri)}
/>)
}
The URI for the source prop has to be dynamic, as the URIs are pulled from a Database.
We've tried storing the entire request in the database (in models/element.js):
const Sequelize = require('sequelize');
const db = require('../db');
const Element = db.define('element', {
sourceViro3DObject: {
type: Sequelize.STRING
}
});
sourceViro3DObject: `require('../../assets/emoji_heart/emoji_heart.vrx')`
When we called it in the React Native class component:
getObjectData = async () => {
try {
const {data} = await axios.get(`/api/elements/${this.props.elementId}`)
this.setState({sourceViro3DObject: data.sourceViro3DObject})
} catch (err) {
console.log(err)
}
}
async componentDidMount() {
await this.getObjectData()
}
But this simply sets state.sourceViro3DObject to a string:
'require('../../assets/emoji_heart/emoji_heart.vrx')'
We've tried setting the filepath directly to state as a string:
state.sourceViro3DObject = '../../assets/emoji_heart/emoji_heart.vrx'
and then call require on it:
require(this.state.sourceViro3DObject)
and received the following error:
Invalid prop `source` supplied to `Viro3DObject`
We've seen recommendations of storing the URIs in an object, but that can't work for us as we don't know what image is going to be used until it's pulled from the database. We can't hard-code them anywhere.
We'd appreciate any help with this!

How to extract data using async and await function in node js?

I tried redis cache implement in node js using mongodb.I set the data in cache.but i cant get the data in cache.how to solve this issue.
cache.js
async function Get_Value(){
let response = await client.get('products')
console.log("_______________")
console.log(response)
}
I got output : true
Excepted output: json data
how to get json data using cache get method
Redis does not provide a full async await adapter for node.js so usually as a workaround people are promisifying the lib.
const { promisify } = require('util');
const getAsync = promisify(client.get).bind(client);
async function getValue(){
let response = await getAsync("products");
}
An other approach to promisify the entire redis library you can use:
const redis = require('redis');
bluebird.promisifyAll(redis);
Now you will be able also to use the methods using async/await.

Variable inside a class is not defined NodeJS

I am develping an application to send emails with nodeJs 6.9 and express 4.
I am also using a library called powerdrill wich is the library that calls Mandrill APIs.
I am trying to use the message variable which is the varible that use the powerdrill library to create the object and send the email. I am using this variable inside a method but is throwing an error.
'use strict';
var config = require('config'),
queries = require('api/queries'),
Message = require('powerdrill').Message;
class MandrillService{
constructor(config, Message) {
this.config = config;
this.Message = Message;
}
welcome(){
//console.log(req.body);
message = new Message();
message.apiKey(config.mandrillKey)
.subject('Welcom')
.template('welcome-email')
.from(config.mandrilEmail)
.to('david#gmail.com')
.tag('complex')
.globalMergeVar('VERIFY_EMAIL','link')
.send(function(err, resp) {
});
}
}
module.exports = new MandrillService(config);
error:
Unhandled rejection ReferenceError: message is not defined
at MandrillService.welcome (/home/user/platform/services/mandrillService.js:28:17)
at /home/user/platform/services/notificationService.js:222:22
at Promise._execute (/home/user//platform/node_modules/bluebird/js/release/debuggability.js:303:9)
at Promise._resolveFromExecutor (/home/user/platform/node_modules/bluebird/js/release/promise.js:483:18)
I donĀ“t know what is the behavior inside a class but if I try to call the method using express inside a post method, and using it like follows the code works fine.
var express = require('express'),
router = express.Router(),
config = require('config'),
Message = require('powerdrill').Message;
router.post('/welcome',function(req,res,next){
message = new Message();
message.apiKey(config.mandrillKey)
.subject(req.body.subject)
.template(req.body.template)
.from(config.mandrilEmail)
.to(req.body.to)
.tag('complex')
.globalMergeVar('VERIFY_EMAIL',req.body.linkVefifyEmail)
.send(function(err, resp)
res.send(resp).end();
});
});

Resources