Shopify Api Scopes that used for this guide:
write_metaobject_definitions
read_metaobject_definitions
write_metaobjects
read_metaobjects
We will use ngrok
tool to create secure tunnel to our express
local server for this get started example.
npm i @drizzle-team/tento
Create a .env
file in the root of your project and add your Shopify Application variables:
SHOPIFY_API_KEY=
SHOPIFY_API_SECRET_KEY=
SHOPIFY_SCOPES=
SHOPIFY_SHOP=
Shopify Api Scopes that used for this guide:
write_metaobject_definitions
read_metaobject_definitions
write_metaobjects
read_metaobjects
Create a schema.ts
file and declare your metaobjects and metafields schema:
As of now Tento only supports one schema file.
import { metaobject, metafield } from '@drizzle-team/tento';
export const description = metafield({
name: "Description",
key: "description",
namespace: "custom",
ownerType: "PRODUCT",
fieldDefinition: (f) => f.multiLineTextField(),
});
export const designer = metaobject({
name: "Designer",
type: "designer",
fieldDefinitions: (f) => ({
name: f.singleLineTextField({
name: "Title",
required: true,
validations: (v) => [v.min(1), v.max(50)],
}),
description: f.multiLineTextField({
name: "Description",
}),
website: f.url({
name: "Website",
}),
}),
});
Start your ngrok tunnel to localhost
using:
ngrok http 5000
We use port 5000 for our get started example, but you can use any port if you need.
Create a index.ts
file and initialize express app. Put hostName
and hostScheme
variables from ngrok.
This is actually official @shopify/shopify-api
OAuth example using express
, you can find it here.
import "dotenv/config";
import "@shopify/shopify-api/adapters/node";
import express from "express";
import {
CookieNotFound,
InvalidOAuthError,
LATEST_API_VERSION,
Session,
shopifyApi,
} from "@shopify/shopify-api";
import * as schema from "./db/schema";
import { tento } from "@drizzle-team/tento";
const shopify = shopifyApi({
apiKey: process.env.SHOPIFY_API_KEY!,
apiSecretKey: process.env.SHOPIFY_API_SECRET_KEY!,
scopes: process.env.SHOPIFY_SCOPES!.split(/,\s*/),
hostName: "***.ngrok-free.app", // ngrok link
hostScheme: "https", // https for ngrok
apiVersion: LATEST_API_VERSION,
isEmbeddedApp: true,
});
async function main() {
const app = express();
app.use(express.json());
// our future Shopify session
let session: Session | undefined = undefined;
const SHOPIFY_SHOP = process.env.SHOPIFY_SHOP!;
app.get("/auth", async (req, res) => {
await shopify.auth.begin({
shop: shopify.utils.sanitizeShop(SHOPIFY_SHOP, true)!,
callbackPath: "/auth/callback",
isOnline: false,
rawRequest: req,
rawResponse: res,
});
});
app.get("/auth/callback", async (req, res) => {
try {
const callback = await shopify.auth.callback({
rawRequest: req,
rawResponse: res,
});
session = callback.session;
/*
session: {
id: string
shop: string
state: string
isOnline: boolean
accessToken: string
scope: string
}
*/
return res.redirect("/");
} catch (e: any) {
if (e instanceof InvalidOAuthError) {
return res.status(400).json({
status: "ERROR",
message: e.message,
code: 400,
});
}
if (e instanceof CookieNotFound) {
await shopify.auth.begin({
shop: shopify.utils.sanitizeShop(SHOPIFY_SHOP, true)!,
callbackPath: "/auth/callback",
isOnline: false,
rawRequest: req,
rawResponse: res,
});
}
}
});
app.get("/", async (req, res) => {
if (!session) {
return res.redirect("/auth");
}
// initialize Shopify Graphql client using session from /auth/callback
const gqlClient = new shopify.clients.Graphql({
session,
});
// initialize Tento client using Shopify Graphql client
const client = tento({ client: gqlClient, schema });
// apply your previouse declared schema to Shopify Store
await client.applySchema();
return res.json({ success: true });
});
app.listen(5000, () => {
console.log("App listening on the port 5000");
});
}
main();
Open Shopify Partners — Login to your account
Click Apps (in the left toolbar) — Click on your App
Click Configuration (in the left toolbar)
Scroll to URLs section and add:
APP URL
https://***.ngrok-free.app/
Allowed redirection URL(s)
https://***.ngrok-free.app/auth/callback
Click Save and Release
To run any TypeScript files, you have several options, but let’s stick with one: using tsx
You’ve already installed tsx
, so we can run our queries now
Run index.ts
script
npx tsx src/index.ts
Open your Shopify Store — Click Apps (in the left toolbar) — Click on your App
Wait until Shopify Store get response from your express server. Once it get it, you’ll see this screen.
After succeed you can go to Settings — Custom data and find generated Metafields in Products and Designer Metaobject definition