import "@shopify/shopify-api/adapters/node";
import { shopifyApi, LATEST_API_VERSION, Session} from "@shopify/shopify-api";
import express from "express";
import dotenv from "dotenv";
import axios from "axios";
dotenv.config();
import cookieParser from 'cookie-parser';
import { initializeApp, applicationDefault, cert } from 'firebase-admin/app';
import { getFirestore, Timestamp, FieldValue, Filter } from 'firebase-admin/firestore';
import serviceAccount from './serviceKey.json' assert { type: 'json' };// const { initializeApp, cert } = require('firebase-admin/app');
initializeApp({
credential: cert(serviceAccount)
});
const db = getFirestore();
const host = "sawfly-wealthy-mosquito.ngrok.app";
console.log(host);
const shopify = shopifyApi({
apiKey: process.env.apiKey,
apiSecretKey: process.env.apiSecretKey,
scopes: ["read_orders", "write_orders", "read_products", "write_products"],
hostName: host,
apiVersion: LATEST_API_VERSION,
});
const app = express();
app.use(cookieParser());
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
console.log(`Ngrok host: https://${host}/`);
console.log(`Ngrok auth host: https://${host}/auth?shop=${process.env.SHOPNAME}`);
console.log(`Ngrok auth callback host: https://${host}/auth/callback`);
console.log(`Ngrok fetch some data host: https://${host}/fetch`);
});
/*
when calling auth, you need the name of the user's store before you
can correctly request the website application
You just ask the user to provide a domain that can be found when they go to:
'https://admin.shopify.com/store/YOURSTORE' -> settings -> top left
below username, copy and paste shopname
*/
app.get("/auth", async (req, res) => {
res.cookie('shopName', req.query.shop);
await shopify.auth.begin({
shop: shopify.utils.sanitizeShop(req.query.shop, true),
callbackPath: "/auth/saveInfoRedirect",
isOnline: false,
rawRequest: req,
rawResponse: res,
});
});
app.get('/auth/saveInfoRedirect', async (req, res) => {
// The library will automatically set the appropriate HTTP headers
const callback = await shopify.auth.callback({
rawRequest: req,
rawResponse: res,
});
res.cookie('shopName', callback.session.shop); //write this to local storage so it can be accessed from
const data = {
session: JSON.stringify(callback.session.toObject()),
};
const response = await db.collection('clients').doc(callback.session.shop).set(data);
res.redirect('/fetch?shopName=' + callback.session.shop);
});
app.get('/fetch', async (req, res) => {
//fetch the path from the url parameters
const path = req.query.path;
const fetchSession = await getSessionFromStorage(req.query.shopName);
const session = new Session(fetchSession);
console.log(session, "reconstructed session");
if (!session) {
res.status(401).send('Session not found, please reauthenticate ');
res.redirect(`/auth?shop=${process.env.SHOPNAME}`);
}
try{
console.log('establishing client...');
const client = new shopify.clients.Rest({
session,
apiVersion: LATEST_API_VERSION,
});
const data = await client.get({
path: path,
});
res.json(data);
}
catch (error) {
console.error(error);
res.status(500).send("somethings not right here")
sleep(1000);
}
});
const getSessionFromStorage = async (name) => {
const doc = await db.collection('clients').doc(name).get();
return JSON.parse(doc.data().session);
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
I have this code and when trying to make a Rest Client I get the error
TypeError: Cannot read properties of undefined (reading 'replace')
at C:\Users\**\Documents\shopify-app-sync\node_modules\@shopify\admin-api-client\dist\rest\client.js:86:30
I don’t really understand what I’m doing wrong, it’s probably obvious, but thanks for any help!