able to pull Products using Shopify GraphQL API
This commit is contained in:
@ -5,6 +5,8 @@
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"prettier.semi": false
|
||||
"prettier.semi": false,
|
||||
"cloudcode.duetAI.project": "beepmill-code",
|
||||
"cloudcode.project": "beepmill-code"
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,43 @@
|
||||
class Config {
|
||||
export class Config {
|
||||
productPhotosFolderId: string
|
||||
shopifyApiKey: string
|
||||
shopifyApiSecretKey: string
|
||||
shopifyAdminApiAccessToken: string
|
||||
shopifyApiURI: string
|
||||
|
||||
constructor() {
|
||||
let ss = SpreadsheetApp.getActive()
|
||||
let s = ss.getSheetByName("vars")
|
||||
|
||||
this.productPhotosFolderId = vlookupByColumns("vars", "key", "productPhotosFolderId", "value")
|
||||
this.productPhotosFolderId = vlookupByColumns(
|
||||
"vars",
|
||||
"key",
|
||||
"productPhotosFolderId",
|
||||
"value"
|
||||
)
|
||||
this.shopifyApiKey = vlookupByColumns(
|
||||
"vars",
|
||||
"key",
|
||||
"shopifyApiKey",
|
||||
"value"
|
||||
)
|
||||
this.shopifyApiSecretKey = vlookupByColumns(
|
||||
"vars",
|
||||
"key",
|
||||
"shopifyApiSecretKey",
|
||||
"value"
|
||||
)
|
||||
this.shopifyAdminApiAccessToken = vlookupByColumns(
|
||||
"vars",
|
||||
"key",
|
||||
"shopifyAdminApiAccessToken",
|
||||
"value"
|
||||
)
|
||||
this.shopifyApiURI = vlookupByColumns(
|
||||
"vars",
|
||||
"key",
|
||||
"shopifyApiURI",
|
||||
"value"
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,22 @@
|
||||
import { Shop } from "./shopifyApi"
|
||||
|
||||
function initMenu() {
|
||||
let ui = SpreadsheetApp.getUi()
|
||||
ui.createMenu("BLM")
|
||||
.addItem("Fill out product from template", "fillProductFromTemplate")
|
||||
.addItem("Create missing photo folders", "createMissingPhotoFolders")
|
||||
.addSeparator()
|
||||
.addItem("Run Shopify Orders", "runShopifyOrders")
|
||||
.addItem("Get Shopify Products", "getShopifyProducts")
|
||||
.addToUi()
|
||||
}
|
||||
|
||||
function runShopifyOrders() {
|
||||
let shop = new Shop()
|
||||
shop.RunOrders()
|
||||
}
|
||||
|
||||
function getShopifyProducts() {
|
||||
let shop = new Shop()
|
||||
shop.GetProducts()
|
||||
}
|
||||
|
||||
732
src/shopifyApi.ts
Normal file
732
src/shopifyApi.ts
Normal file
@ -0,0 +1,732 @@
|
||||
// EXTREMELY inspired by https://github.com/webdjoe/shopify_apps_script/blob/master/shopify_api.gs
|
||||
|
||||
// Create a private App in Shopify admin and insert app password below
|
||||
// Sheets need to be created before running with columns of desired output set
|
||||
// Use keys found in Shopify Rest API Order Object as row headers
|
||||
// https://shopify.dev/api/admin-rest/2022-04/resources/order#resource-object
|
||||
|
||||
// Supports the following sheets/order objects with default columns -
|
||||
// orders - id, number, order_name, name, current_total_discounts, current_total_price, current_subtotal_price, current_total_tax, financial_status, landing_site, created_at, processed_at, processing_method, subtotal_price, source_url, tags, token, total_discounts, total_line_items_price, total_price, total_tax, updated_at
|
||||
// shipping_lines - order_id, ordered_at, code, price, title, source, discounted_price, carrier_identifier
|
||||
// discount_applications - order_id, created_at, type, title, value, value_type, code, description, target_type, target_selection, allocation_method, ordered_at
|
||||
// refunds = id, order_id, ordered_at, created_at, note, transaction_id, kind, amount
|
||||
// line_items = id, order_id, sku, name, price, title, vendor, quantity, product_id, variant_id, variant_title, total_discount, fulfillment_status, ordered_at
|
||||
// customer - order_id, ordered_at, id, email, phone, last_name, created_at, first_name, admin_graphql_api_id, updated_at, orders_count, last_order_id
|
||||
|
||||
/// <reference types="@types/google-apps-script" />
|
||||
|
||||
import { Config } from "./config"
|
||||
|
||||
const ss = SpreadsheetApp.getActive()
|
||||
|
||||
const today = new Date()
|
||||
const thirty_days = new Date(
|
||||
today.getFullYear(),
|
||||
today.getMonth() - 1,
|
||||
today.getDate()
|
||||
)
|
||||
const start_str = Utilities.formatDate(
|
||||
thirty_days,
|
||||
SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(),
|
||||
"yyyy-MM-dd"
|
||||
)
|
||||
const end_str = Utilities.formatDate(
|
||||
today,
|
||||
SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(),
|
||||
"yyyy-MM-dd"
|
||||
)
|
||||
|
||||
const orders = "_orders"
|
||||
const line_items = "_line_items"
|
||||
const customer = "_customer"
|
||||
const refunds = "_refunds"
|
||||
const shipping_lines = "_shipping_lines"
|
||||
const discount_applications = "_discount_applications"
|
||||
|
||||
function makeArray(headers, obj_list) {
|
||||
var rng_arr = []
|
||||
for (let obj of obj_list) {
|
||||
var line_arr = []
|
||||
headers.forEach((item) => {
|
||||
var line_item = item in obj ? obj[item] : ""
|
||||
if (Array.isArray(line_item)) {
|
||||
line_item = line_item.toString()
|
||||
}
|
||||
line_arr.push(line_item)
|
||||
})
|
||||
rng_arr.push(line_arr)
|
||||
}
|
||||
return rng_arr
|
||||
}
|
||||
|
||||
function makeDiscountsArray(orders_arr) {
|
||||
var disc_arr = []
|
||||
var headers = getDiscountHeaders()
|
||||
for (let ord of orders_arr) {
|
||||
var disc_list = ord.discount_applications
|
||||
if (disc_list.length < 1) {
|
||||
continue
|
||||
}
|
||||
disc_list.forEach((disc) => {
|
||||
var disc_line = []
|
||||
disc["order_id"] = ord["id"]
|
||||
disc["ordered_at"] = ord["created_at"]
|
||||
headers.forEach((head) => {
|
||||
var itm = head in disc ? disc[head] : ""
|
||||
disc_line.push(itm)
|
||||
})
|
||||
disc_arr.push(disc_line)
|
||||
})
|
||||
}
|
||||
return disc_arr
|
||||
}
|
||||
|
||||
function makeCustomerArray(orders_arr) {
|
||||
var cust_arr = []
|
||||
var headers = getCustomerHeaders()
|
||||
for (let ord of orders_arr) {
|
||||
var cust_obj = ord.customer
|
||||
if (typeof cust_obj == "undefined") {
|
||||
continue
|
||||
}
|
||||
var customer_line = []
|
||||
cust_obj["order_id"] = ord["id"]
|
||||
cust_obj["ordered_at"] = ord["created_at"]
|
||||
headers.forEach((head) => {
|
||||
var itm = head in cust_obj ? cust_obj[head] : ""
|
||||
customer_line.push(itm)
|
||||
})
|
||||
cust_arr.push(customer_line)
|
||||
}
|
||||
return cust_arr
|
||||
}
|
||||
|
||||
function makeLIArray(orders_arr) {
|
||||
var line_arr = []
|
||||
var headers = getLineItemHeaders()
|
||||
for (let ord of orders_arr) {
|
||||
var line_items_list = ord.line_items
|
||||
if (line_items_list.length < 1) {
|
||||
continue
|
||||
}
|
||||
line_items_list.forEach((li_obj) => {
|
||||
var li_line = []
|
||||
li_obj["ordered_at"] = ord["created_at"]
|
||||
li_obj["order_id"] = ord["id"]
|
||||
headers.forEach((head) => {
|
||||
var itm = head in li_obj ? li_obj[head] : ""
|
||||
li_line.push(itm)
|
||||
})
|
||||
line_arr.push(li_line)
|
||||
})
|
||||
}
|
||||
return line_arr
|
||||
}
|
||||
|
||||
function makeShippingArray(orders_arr) {
|
||||
var ship_arr = []
|
||||
var header = getShippingHeaders()
|
||||
for (let ord of orders_arr) {
|
||||
var ship_list = ord.shipping_lines
|
||||
if (ship_list.length < 1) {
|
||||
continue
|
||||
}
|
||||
|
||||
ship_list.forEach((ship_obj) => {
|
||||
var line = []
|
||||
|
||||
ship_obj["ordered_at"] = ord["created_at"]
|
||||
ship_obj["order_id"] = ord["id"]
|
||||
|
||||
header.forEach((a) => {
|
||||
var line_itm = a in ship_obj ? ship_obj[a] : ""
|
||||
line.push(line_itm)
|
||||
})
|
||||
ship_arr.push(line)
|
||||
})
|
||||
}
|
||||
return ship_arr
|
||||
}
|
||||
|
||||
function makeRefundsArray(orders_arr) {
|
||||
var refunds_arr = []
|
||||
var header = getRefundHeaders()
|
||||
for (let ord of orders_arr) {
|
||||
var ref_list = ord.refunds
|
||||
if (ref_list.length < 1) {
|
||||
continue
|
||||
}
|
||||
|
||||
ref_list.forEach((ref_obj) => {
|
||||
var line = []
|
||||
|
||||
ref_obj["ordered_at"] = ord["created_at"]
|
||||
if (ref_obj["transactions"].length == 1) {
|
||||
var trans = ref_obj["transactions"][0]
|
||||
ref_obj["transaction_id"] = trans["id"]
|
||||
ref_obj["amount"] = trans["amount"]
|
||||
ref_obj["kind"] = trans["kind"]
|
||||
} else {
|
||||
return
|
||||
}
|
||||
header.forEach((a) => {
|
||||
var line_itm = a in ref_obj ? ref_obj[a] : ""
|
||||
line.push(line_itm)
|
||||
})
|
||||
refunds_arr.push(line)
|
||||
})
|
||||
}
|
||||
return refunds_arr
|
||||
}
|
||||
|
||||
function appendRows(sht_name, arr) {
|
||||
var sht = ss.getSheetByName(sht_name)
|
||||
let last_row = sht.getLastRow()
|
||||
sht.getRange(last_row + 1, 1, arr.length, arr[0].length).setValues(arr)
|
||||
}
|
||||
|
||||
function processDataRange(sht_name) {
|
||||
var sh = ss.getSheetByName(sht_name)
|
||||
var data_rng = sh.getDataRange().offset(1, 0, sh.getLastRow() - 1)
|
||||
var data = data_rng.getValues()
|
||||
|
||||
var targetData = new Array()
|
||||
for (let n = 0; n < data.length; ++n) {
|
||||
if (data[n].join().replace(/,/g, "") != "") {
|
||||
targetData.push(data[n])
|
||||
}
|
||||
}
|
||||
data_rng.clear()
|
||||
targetData.sort((a, b) => a[1] - b[1])
|
||||
sh.getRange(2, 1, targetData.length, targetData[0].length).setValues(
|
||||
targetData
|
||||
)
|
||||
}
|
||||
|
||||
function removeDuplicates(obj_list, sht_name, id = "id") {
|
||||
var sht = ss.getSheetByName(sht_name)
|
||||
var sht_arr = sht.getDataRange().getValues()
|
||||
for (let a = 0; a < sht_arr[0].length; a++) {
|
||||
if (sht_arr[0][a] == id) {
|
||||
var id_col = a
|
||||
break
|
||||
}
|
||||
}
|
||||
for (let x = 0; x < sht_arr.length; x++) {
|
||||
var row_id = sht_arr[x][id_col]
|
||||
for (let y = 0; y < obj_list.length; y++) {
|
||||
if (obj_list[y][id_col] == row_id) {
|
||||
sht.getRange(x + 1, 1, 1, sht_arr[0].length).clearContent()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function removeAllDuplicates(obj_list, sht_name, id = "id") {
|
||||
var sht = ss.getSheetByName(sht_name)
|
||||
var sht_arr = sht.getDataRange().getValues()
|
||||
for (let a = 0; a < sht_arr[0].length; a++) {
|
||||
if (sht_arr[0][a] == id) {
|
||||
var id_col = a
|
||||
break
|
||||
}
|
||||
}
|
||||
for (let x = 0; x < sht_arr.length; x++) {
|
||||
var row_id = sht_arr[x][id_col]
|
||||
for (let y = 0; y < obj_list.length; y++) {
|
||||
if (obj_list[y][id_col] == row_id) {
|
||||
sht.getRange(x + 1, 1, 1, sht_arr[0].length).clearContent()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getColumnList() {
|
||||
var order_list = getOrderHeaders()
|
||||
order_list.push(
|
||||
line_items,
|
||||
customer,
|
||||
refunds,
|
||||
discount_applications,
|
||||
shipping_lines
|
||||
)
|
||||
return order_list
|
||||
}
|
||||
|
||||
function getColumns(data: string) {
|
||||
var sht = ss.getSheetByName(data)
|
||||
if (sht == null) {
|
||||
ss.insertSheet(data)
|
||||
sht = ss.getSheetByName(data)
|
||||
}
|
||||
if (sht == null) {
|
||||
throw new Error("unable to get/create sheet " + data)
|
||||
}
|
||||
var last_col = sht.getLastColumn()
|
||||
var header_list = sht.getRange(1, 1, 1, last_col).getValues()
|
||||
return header_list[0]
|
||||
}
|
||||
|
||||
function getShippingHeaders() {
|
||||
return getColumns(shipping_lines)
|
||||
}
|
||||
|
||||
function getCustomerHeaders() {
|
||||
return getColumns(customer)
|
||||
}
|
||||
|
||||
function getLineItemHeaders() {
|
||||
return getColumns(line_items)
|
||||
}
|
||||
|
||||
function getOrderHeaders() {
|
||||
return Order.columns
|
||||
}
|
||||
|
||||
function getDiscountHeaders() {
|
||||
return getColumns(discount_applications)
|
||||
}
|
||||
|
||||
function getRefundHeaders() {
|
||||
return getColumns(refunds)
|
||||
}
|
||||
function customerTable(orders_arr) {
|
||||
var rng_arr = makeCustomerArray(orders_arr)
|
||||
removeDuplicates(rng_arr, customer, "order_id")
|
||||
SpreadsheetApp.flush()
|
||||
appendRows(customer, rng_arr)
|
||||
SpreadsheetApp.flush()
|
||||
processDataRange(customer)
|
||||
}
|
||||
|
||||
function discountsTable(orders_arr) {
|
||||
var rng_arr = makeDiscountsArray(orders_arr)
|
||||
if (rng_arr.length > 0) {
|
||||
removeAllDuplicates(rng_arr, discount_applications, "order_id")
|
||||
SpreadsheetApp.flush()
|
||||
appendRows(discount_applications, rng_arr)
|
||||
SpreadsheetApp.flush()
|
||||
processDataRange(discount_applications)
|
||||
}
|
||||
}
|
||||
|
||||
function ordersTable(orders_arr) {
|
||||
var rng_arr = makeArray(getOrderHeaders(), orders_arr)
|
||||
removeDuplicates(rng_arr, orders, "id")
|
||||
SpreadsheetApp.flush()
|
||||
appendRows(orders, rng_arr)
|
||||
SpreadsheetApp.flush()
|
||||
processDataRange(orders)
|
||||
}
|
||||
|
||||
function refundsTable(orders_arr) {
|
||||
var rng_arr = makeRefundsArray(orders_arr)
|
||||
if (rng_arr.length > 0) {
|
||||
removeDuplicates(rng_arr, refunds, "id")
|
||||
SpreadsheetApp.flush()
|
||||
appendRows(refunds, rng_arr)
|
||||
SpreadsheetApp.flush()
|
||||
processDataRange(refunds)
|
||||
}
|
||||
}
|
||||
|
||||
function lineItemsTable(orders_arr) {
|
||||
var rng_arr = makeLIArray(orders_arr)
|
||||
removeDuplicates(rng_arr, line_items, "id")
|
||||
SpreadsheetApp.flush()
|
||||
appendRows(line_items, rng_arr)
|
||||
SpreadsheetApp.flush()
|
||||
processDataRange(line_items)
|
||||
}
|
||||
|
||||
function shippingTable(orders_arr) {
|
||||
var rng_arr = makeShippingArray(orders_arr)
|
||||
if (rng_arr.length > 0) {
|
||||
removeDuplicates(rng_arr, shipping_lines, "order_id")
|
||||
SpreadsheetApp.flush()
|
||||
appendRows(shipping_lines, rng_arr)
|
||||
SpreadsheetApp.flush()
|
||||
processDataRange(shipping_lines)
|
||||
}
|
||||
}
|
||||
|
||||
function unquote(value) {
|
||||
if (value.charAt(0) == '"' && value.charAt(value.length - 1) == '"')
|
||||
return value.substring(1, value.length - 1)
|
||||
return value
|
||||
}
|
||||
|
||||
function parseLinkHeader(header) {
|
||||
var linkexp =
|
||||
/<[^>]*>\s*(\s*;\s*[^\(\)<>@,;:"\/\[\]\?={} \t]+=(([^\(\)<>@,;:"\/\[\]\?={} \t]+)|("[^"]*")))*(,|$)/g
|
||||
var paramexp =
|
||||
/[^\(\)<>@,;:"\/\[\]\?={} \t]+=(([^\(\)<>@,;:"\/\[\]\?={} \t]+)|("[^"]*"))/g
|
||||
|
||||
var matches = header.match(linkexp)
|
||||
var rels = {}
|
||||
for (let i = 0; i < matches.length; i++) {
|
||||
var split = matches[i].split(">")
|
||||
var href = split[0].substring(1)
|
||||
var ps = split[1]
|
||||
var link = {
|
||||
href: "",
|
||||
rel: "",
|
||||
}
|
||||
link.href = href
|
||||
var s = ps.match(paramexp)
|
||||
for (let j = 0; j < s.length; j++) {
|
||||
var p = s[j]
|
||||
var paramsplit = p.split("=")
|
||||
var name = paramsplit[0]
|
||||
link[name] = unquote(paramsplit[1])
|
||||
}
|
||||
|
||||
if (link.rel !== undefined) {
|
||||
rels[link.rel] = link
|
||||
}
|
||||
}
|
||||
|
||||
return rels
|
||||
}
|
||||
|
||||
export class Shop {
|
||||
private shopifyApiKey: string
|
||||
private shopifyApiSecretKey: string
|
||||
private shopifyAdminApiAccessToken: string
|
||||
private shopifyApiURI: string
|
||||
static endpoints = {
|
||||
orders: "/admin/api/2022-04/orders.json",
|
||||
graphql: "/admin/api/2024-10/graphql.json",
|
||||
}
|
||||
|
||||
constructor() {
|
||||
let config = new Config()
|
||||
this.shopifyApiKey = config.shopifyApiKey
|
||||
this.shopifyApiSecretKey = config.shopifyApiSecretKey
|
||||
this.shopifyAdminApiAccessToken = config.shopifyAdminApiAccessToken
|
||||
this.shopifyApiURI = config.shopifyApiURI
|
||||
}
|
||||
|
||||
RunOrders(start = "", end = "") {
|
||||
if (start === "" || end === "") {
|
||||
start = start_str
|
||||
end = end_str
|
||||
}
|
||||
const date_exp = /^\d{4}[\-](0?[1-9]|1[012])[\-](0?[1-9]|[12][0-9]|3[01])$/
|
||||
if (!date_exp.test(start) || !date_exp.test(end)) {
|
||||
Logger.log("Dates must be in yyyy-MM-dd format")
|
||||
return
|
||||
}
|
||||
this.GetOrders(start, end)
|
||||
}
|
||||
|
||||
GetOrders(start: string, end: string) {
|
||||
let endpoint = Shop.endpoints.orders
|
||||
var params = {
|
||||
created_at_min: start,
|
||||
created_at_max: end,
|
||||
fields: getColumnList(),
|
||||
}
|
||||
|
||||
var done = false
|
||||
var next_link = ""
|
||||
do {
|
||||
if (next_link === "") {
|
||||
var response = this.shopifyAPI(endpoint, params)
|
||||
console.log(response)
|
||||
} else {
|
||||
var response = this.shopifyAPI(endpoint, params, next_link)
|
||||
console.log(response)
|
||||
}
|
||||
let resp = response.content
|
||||
let headers = response.headers
|
||||
var orders_arr: Order[] = resp["orders"]
|
||||
if (orders_arr.length < 1) {
|
||||
console.log("No orders found")
|
||||
done = true
|
||||
continue
|
||||
}
|
||||
var cols = getColumnList()
|
||||
var numColumns = cols.length
|
||||
var respKeys = Object.keys(orders_arr[0])
|
||||
var respCols = respKeys.length
|
||||
if (cols.filter((x) => respKeys.indexOf(x) === -1).length !== 0) {
|
||||
Logger.log(
|
||||
"Keys missing from return - " +
|
||||
cols.filter((x) => respKeys.indexOf(x) === -1)
|
||||
)
|
||||
return
|
||||
}
|
||||
ordersTable(orders_arr)
|
||||
refundsTable(orders_arr)
|
||||
lineItemsTable(orders_arr)
|
||||
customerTable(orders_arr)
|
||||
discountsTable(orders_arr)
|
||||
shippingTable(orders_arr)
|
||||
|
||||
if (headers["Link"] !== undefined) {
|
||||
var links = parseLinkHeader(headers["Link"])
|
||||
Logger.log(headers["Link"])
|
||||
if (links["next"] === undefined) {
|
||||
done = true
|
||||
} else {
|
||||
next_link = links["next"]["href"]
|
||||
Logger.log(next_link)
|
||||
}
|
||||
} else {
|
||||
done = true
|
||||
}
|
||||
} while (!done)
|
||||
}
|
||||
|
||||
GetProducts() {
|
||||
let done = false
|
||||
let cursor = ""
|
||||
let fields = ["id", "title"]
|
||||
var response = {
|
||||
content: {},
|
||||
headers: {},
|
||||
}
|
||||
let products: Product[] = []
|
||||
do {
|
||||
let query = new ProductsQuery(fields, cursor)
|
||||
response = this.shopifyGraphQLAPI(query.JSON)
|
||||
console.log(response)
|
||||
let productsResponse = new ProductsResponse(response.content)
|
||||
if (productsResponse.products.edges.length <= 0) {
|
||||
console.log("no products returned")
|
||||
done = true
|
||||
continue
|
||||
}
|
||||
for (let i = 0; i < productsResponse.products.edges.length; i++) {
|
||||
let edge = productsResponse.products.edges[i]
|
||||
console.log(JSON.stringify(edge))
|
||||
let p = new Product()
|
||||
Object.assign(edge.node, p)
|
||||
products.push(p)
|
||||
}
|
||||
if (productsResponse.products.pageInfo.hasNextPage) {
|
||||
cursor = productsResponse.products.pageInfo.endCursor
|
||||
} else {
|
||||
done = true
|
||||
}
|
||||
} while (!done)
|
||||
}
|
||||
|
||||
shopifyAPI(endpoint: string, query: {}, next = "") {
|
||||
var options: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions = {
|
||||
method: "get",
|
||||
headers: {
|
||||
"X-Shopify-Access-Token": this.shopifyAdminApiAccessToken,
|
||||
},
|
||||
}
|
||||
if (next == "") {
|
||||
var url = this.buildURL(endpoint, query)
|
||||
var resp = UrlFetchApp.fetch(url, options)
|
||||
console.log(resp.getContentText())
|
||||
} else {
|
||||
var url = next
|
||||
var resp = UrlFetchApp.fetch(url, options)
|
||||
console.log(resp.getContentText())
|
||||
}
|
||||
|
||||
return {
|
||||
content: JSON.parse(resp.getContentText()),
|
||||
headers: resp.getHeaders(),
|
||||
}
|
||||
}
|
||||
|
||||
shopifyGraphQLAPI(query: {}, next = "") {
|
||||
let endpoint = Shop.endpoints.graphql
|
||||
let options: GoogleAppsScript.URL_Fetch.URLFetchRequestOptions = {
|
||||
method: "post",
|
||||
payload: JSON.stringify(query),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"X-Shopify-Access-Token": this.shopifyAdminApiAccessToken,
|
||||
},
|
||||
muteHttpExceptions: true,
|
||||
}
|
||||
var url = this.buildURL(endpoint)
|
||||
console.log(UrlFetchApp.getRequest(url, options))
|
||||
var resp = UrlFetchApp.fetch(url, options)
|
||||
console.log(resp.getContentText())
|
||||
|
||||
return {
|
||||
content: JSON.parse(resp.getContentText()),
|
||||
headers: resp.getHeaders(),
|
||||
}
|
||||
}
|
||||
|
||||
buildURL(endpoint: string, params = {}) {
|
||||
var url = this.shopifyApiURI + endpoint
|
||||
if (params !== undefined && Object.keys(params).length > 0) {
|
||||
let i = 0
|
||||
for (let p in params) {
|
||||
if (i === 0) {
|
||||
url += "?" + p + "=" + encodeURIComponent(params[p])
|
||||
} else {
|
||||
url += "&" + p + "=" + encodeURIComponent(params[p])
|
||||
}
|
||||
i++
|
||||
}
|
||||
}
|
||||
return url
|
||||
}
|
||||
}
|
||||
|
||||
export class Order {
|
||||
static columns = [
|
||||
"id",
|
||||
"number",
|
||||
"order_name",
|
||||
"name",
|
||||
"current_total_discounts",
|
||||
"current_total_price",
|
||||
"current_subtotal_price",
|
||||
"current_total_tax",
|
||||
"financial_status",
|
||||
"landing_site",
|
||||
"created_at",
|
||||
"processed_at",
|
||||
"processing_method",
|
||||
"subtotal_price",
|
||||
"source_url",
|
||||
"tags",
|
||||
"token",
|
||||
"total_discounts",
|
||||
"total_line_items_price",
|
||||
"total_price",
|
||||
"total_tax",
|
||||
"updated_at",
|
||||
]
|
||||
|
||||
constructor() {
|
||||
for (let i = 0; i < Order.columns.length; i++) {
|
||||
this[Order.columns[i]] = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Product {
|
||||
body_html: string
|
||||
created_at: Date
|
||||
handle: string
|
||||
id: number
|
||||
images: ProductImage[]
|
||||
options: ProductOption[]
|
||||
product_type: string
|
||||
published_at: Date
|
||||
published_scope: string
|
||||
status: string
|
||||
tags: string[]
|
||||
template_suffix: string
|
||||
title: string
|
||||
updated_at: Date
|
||||
variants: ProductVariant[]
|
||||
vendor: string
|
||||
}
|
||||
|
||||
class ProductImage {
|
||||
id: number
|
||||
product_id: number
|
||||
position: number
|
||||
created_at: Date
|
||||
updated_at: Date
|
||||
width: number
|
||||
height: number
|
||||
src: string
|
||||
variant_ids: number[]
|
||||
}
|
||||
|
||||
class ProductOption {
|
||||
id: number
|
||||
product_id: number
|
||||
name: string
|
||||
position: number
|
||||
values: string[]
|
||||
}
|
||||
|
||||
class ProductVariant {
|
||||
barcode: string
|
||||
compare_at_price: number
|
||||
created_at: Date
|
||||
fulfillment_service: string
|
||||
grams: number
|
||||
weight: number
|
||||
weight_unit: string
|
||||
id: number
|
||||
inventory_item_id: number
|
||||
inventory_management: string
|
||||
inventory_policy: string
|
||||
inventory_quantity: number
|
||||
option1: string
|
||||
position: number
|
||||
price: number
|
||||
product_id: number
|
||||
requires_shipping: boolean
|
||||
sku: string
|
||||
taxable: boolean
|
||||
title: string
|
||||
updated_at: Date
|
||||
}
|
||||
|
||||
class Products {
|
||||
edges: ProductEdge[]
|
||||
pageInfo: PageInfo
|
||||
}
|
||||
|
||||
class ProductEdge {
|
||||
node: Product
|
||||
cursor: string
|
||||
}
|
||||
|
||||
class PageInfo {
|
||||
hasNextPage: boolean
|
||||
hasPreviousPage: boolean
|
||||
startCursor: string
|
||||
endCursor: string
|
||||
}
|
||||
|
||||
class ProductsQuery {
|
||||
GQL: string
|
||||
JSON: JSON
|
||||
constructor(
|
||||
fields: string[] = ["id", "title", "handle"],
|
||||
cursor: string = ""
|
||||
) {
|
||||
let cursorText: string
|
||||
if (cursor == "") {
|
||||
cursorText = ""
|
||||
} else {
|
||||
cursorText = `, after: "${cursor}"`
|
||||
}
|
||||
this.GQL = `{
|
||||
products(first: 10${cursorText}) {
|
||||
edges {
|
||||
node { ${fields.join(" ")} }
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
endCursor
|
||||
}
|
||||
}
|
||||
}`
|
||||
let j = `{"query": ${formatGqlForJSON(this.GQL)}}`
|
||||
console.log(j)
|
||||
this.JSON = JSON.parse(j)
|
||||
}
|
||||
}
|
||||
|
||||
class ProductsResponse {
|
||||
products: Products
|
||||
constructor(response: {}) {
|
||||
this.products = response["data"]["products"]
|
||||
}
|
||||
}
|
||||
|
||||
function formatGqlForJSON(gql: string) {
|
||||
let singleLine = gql.split("\n").join(" ").replace(/\s+/g, " ")
|
||||
return JSON.stringify(singleLine)
|
||||
}
|
||||
Reference in New Issue
Block a user