App reviews, troubleshooting, and recommendations
We're moving the community! Starting July 7, the current community will be read-only for approx. 2 weeks. You can browse content, but posting will be temporarily unavailable. Learn more
We have a Shopify app built using node, react, and Prisma.
web/shopify.js
import { BillingInterval, LATEST_API_VERSION } from "@shopify/shopify-api";
import { shopifyApp } from '@shopify/shopify-app-express';
import { restResources } from "@shopify/shopify-api/rest/admin/2023-04";
import { PrismaSessionStorage } from '@shopify/shopify-app-session-storage-prisma';
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
const storage = new PrismaSessionStorage(prisma);
const shopify = shopifyApp({
api: {
apiVersion: LATEST_API_VERSION,
restResources,
billing: undefined,
isEmbeddedApp: true,
},
auth: {
path: "/api/auth",
callbackPath: "/api/auth/callback",
},
webhooks: {
path: "/api/webhooks",
},
sessionStorage: storage
});
export default shopify;
web/index.js file
// @TS-check
import path from "path";
import fs from "fs";
import express from "express";
import serveStatic from "serve-static";
import {
upsertConfig,
getConfigById,
deleteConfigById,
getLastRecord,
syncHistoricalData,
} from "./controllers/ConfigController.js";
import { createOrder, createReturnOrder } from "./controllers/OrderController.js";
import shopify from "./shopify.js";
import webhookHandlers from "./webhook-handlers.js";
const PORT = parseInt(process.env.BACKEND_PORT || process.env.PORT, 10);
const STATIC_PATH = path.join(process.cwd(), process.env.NODE_ENV === "production" ? "frontend/dist" : "frontend");
const app = express();
// Middleware
app.use(express.json());
app.use(shopify.cspHeaders());
app.use(serveStatic(STATIC_PATH, { index: false }));
// Shopify authentication and webhook handling
app.get(shopify.config.auth.path, shopify.auth.begin());
app.get(shopify.config.auth.callbackPath, shopify.auth.callback(), shopify.redirectToShopifyOrAppRoot());
app.post(shopify.config.webhooks.path, shopify.processWebhooks({ webhookHandlers }));
// Middleware for validating authenticated session
const validateSession = shopify.validateAuthenticatedSession();
// API routes with authentication
app.post("/api/config", validateSession, upsertConfig);
app.get("/api/config/:id", validateSession, getConfigById);
app.delete("/api/config/:id", validateSession, deleteConfigById);
app.get("/api/get-last-record", validateSession, getLastRecord);
app.get("/api/sync-historical-data", validateSession, syncHistoricalData);
app.patch("/api/order/create/:id", validateSession, createOrder);
// Public API route
app.post("/api/order/return/create", createReturnOrder);
// Default route
app.use("/*", shopify.ensureInstalledOnShop(), (_req, res) => {
const filePath = path.join(STATIC_PATH, "index.html");
const fileContent = fs.readFileSync(filePath, "utf-8");
res.status(200).type("text/html").send(fileContent);
});
app.listen(PORT, () => {
console.log(`Server listening on port ${PORT}`);
});