diff --git a/.keystone/config.js b/.keystone/config.js index 4b509de..c5c8e44 100644 --- a/.keystone/config.js +++ b/.keystone/config.js @@ -150,7 +150,7 @@ async function getProductFunction({ console.log("OpenFront Channel getProductFunction called with:", { platform: platform.domain, productId, variantId }); const openFrontClient = await createOpenFrontClient(platform); const gqlQuery = import_graphql_request.gql` - query GetChannelProduct($productId: ID!, $variantId: ID) { + query GetChannelProduct($productId: ID!, $variantWhere: ProductVariantWhereInput) { product(where: { id: $productId }) { id title @@ -161,7 +161,7 @@ async function getProductFunction({ } imagePath } - productVariants(where: $variantId ? { id: { equals: $variantId } } : {}) { + productVariants(where: $variantWhere) { id title sku @@ -180,7 +180,7 @@ async function getProductFunction({ `; const { product } = await openFrontClient.request(gqlQuery, { productId, - variantId + variantWhere: variantId ? { id: { equals: variantId } } : {} }); if (!product || product.status !== "published") { throw new Error("Product not available for fulfillment from OpenFront"); @@ -211,91 +211,161 @@ async function createPurchaseFunction({ }) { console.log(`\u{1F6D2} OpenFront Channel: Creating purchase with ${cartItems.length} items`); console.log(`\u{1F69A} OpenFront Channel: Ship to: ${shipping?.firstName} ${shipping?.lastName}`); + console.log(`\u{1F4E6} OpenFront Channel: Full shipping data:`, JSON.stringify(shipping, null, 2)); + console.log(`\u{1F4E6} OpenFront Channel: Platform data:`, JSON.stringify(platform, null, 2)); + console.log(`\u{1F4E6} OpenFront Channel: Cart items:`, JSON.stringify(cartItems, null, 2)); const openFrontClient = await createOpenFrontClient(platform); - const purchaseId = `PO-OF-${Date.now()}`; - const orderNumber = `#${purchaseId}`; - const totalPrice = cartItems.reduce((sum, item) => { - return sum + parseFloat(item.price) * item.quantity; - }, 0); - const createOrderMutation = import_graphql_request.gql` - mutation CreateFulfillmentOrder($data: OrderCreateInput!) { - createOrder(data: $data) { - id - orderNumber - total - status - orderLineItems { + try { + const currencyCode = (shipping?.currency || "USD").toLowerCase(); + const getRegionQuery = import_graphql_request.gql` + query GetRegion($currencyCode: String!) { + regions(where: { currency: { code: { equals: $currencyCode } } }) { id - title - quantity - unitPrice - productVariant { + taxRate + currency { id - title - sku - product { + code + } + } + } + `; + const { regions } = await openFrontClient.request(getRegionQuery, { + currencyCode + }); + const region = regions[0]; + if (!region) { + throw new Error(`No region found for currency: ${currencyCode}`); + } + console.log("\u{1F6D2} [OpenFront Channel] Creating cart with region:", region.id); + const { createCart: cart } = await openFrontClient.request(import_graphql_request.gql` + mutation CreateCart($data: CartCreateInput!) { + createCart(data: $data) { + id + region { + id + currency { id - title + code } } } } - } - `; - try { - const orderData = { - orderNumber, - customerEmail: shipping?.email || "fulfillment@openship.org", - firstName: shipping?.firstName || "Fulfillment", - lastName: shipping?.lastName || "Order", - address1: shipping?.streetAddress1 || "", - address2: shipping?.streetAddress2 || "", - city: shipping?.city || "", - state: shipping?.state || "", - postalCode: shipping?.zip || "", - countryCode: shipping?.country || "US", - phone: shipping?.phone || "", - total: Math.round(totalPrice * 100), - // Convert to cents - subtotal: Math.round(totalPrice * 100), - status: "pending_fulfillment", - orderLineItems: { - create: cartItems.map((item) => ({ - title: item.name || `Product ${item.variantId}`, - quantity: item.quantity, - unitPrice: Math.round(parseFloat(item.price) * 100), - // Convert to cents - productVariant: { connect: { id: item.variantId } } - })) + `, { + data: { + region: { connect: { id: region.id } }, + email: shipping?.email || `order-${Date.now()}@openship.generated` } - }; - const result = await openFrontClient.request(createOrderMutation, { - data: orderData }); - const order = result.createOrder; - console.log(`\u{1F4E7} OpenFront Channel: Fulfillment Order Created: ${orderNumber}`); - console.log(`\u{1F4B0} OpenFront Channel: Total: $${totalPrice.toFixed(2)}`); - const processedLineItems = order.orderLineItems.map((item) => ({ - id: item.id, - title: item.title, + console.log("\u2705 [OpenFront Channel] Cart created with ID:", cart.id); + const lineItemsToCreate = []; + for (const item of cartItems) { + lineItemsToCreate.push({ + productVariant: { connect: { id: item.variantId } }, + quantity: item.quantity + }); + } + console.log("\u{1F4E6} [OpenFront Channel] Adding", lineItemsToCreate.length, "line items to cart"); + await openFrontClient.request(import_graphql_request.gql` + mutation AddLineItemsToCart($cartId: ID!, $data: CartUpdateInput!) { + updateActiveCart(cartId: $cartId, data: $data) { + id + } + } + `, { + cartId: cart.id, + data: { + lineItems: { + create: lineItemsToCreate + } + } + }); + console.log("\u2705 [OpenFront Channel] Line items added to cart"); + console.log("\u{1F4CD} [OpenFront Channel] Creating shipping address"); + const { createAddress: shippingAddr } = await openFrontClient.request(import_graphql_request.gql` + mutation CreateAddress($data: AddressCreateInput!) { + createAddress(data: $data) { + id + } + } + `, { + data: { + firstName: shipping?.firstName || "Guest", + lastName: shipping?.lastName || "Customer", + address1: shipping?.address1 || "123 Default St", + city: shipping?.city || "Default City", + province: shipping?.state || "NY", + postalCode: shipping?.zip || "10001", + phone: shipping?.phone || "", + country: { + connect: { + iso2: (shipping?.country || "US").toLowerCase() + } + } + } + }); + console.log("\u2705 [OpenFront Channel] Shipping address created:", shippingAddr.id); + await openFrontClient.request(import_graphql_request.gql` + mutation UpdateCartAddresses($cartId: ID!, $data: CartUpdateInput!) { + updateActiveCart(cartId: $cartId, data: $data) { + id + } + } + `, { + cartId: cart.id, + data: { + shippingAddress: { connect: { id: shippingAddr.id } }, + billingAddress: { connect: { id: shippingAddr.id } } + } + }); + console.log("\u2705 [OpenFront Channel] Cart updated with addresses"); + console.log("\u{1F3AF} [OpenFront Channel] Completing cart to create order"); + console.log("\u{1F3AF} [OpenFront Channel] Calling completeActiveCart for cart:", cart.id); + const completeResult = await openFrontClient.request(import_graphql_request.gql` + mutation CompleteActiveCart($cartId: ID!) { + completeActiveCart(cartId: $cartId) + } + `, { + cartId: cart.id + }); + console.log("\u{1F50D} [OpenFront Channel] completeActiveCart result:", JSON.stringify(completeResult, null, 2)); + const order = completeResult.completeActiveCart; + if (!order?.id) { + throw new Error("Failed to complete cart - no order created"); + } + console.log("\u{1F50D} [OpenFront Channel] COMPLETE ORDER RESULT:", JSON.stringify(order, null, 2)); + console.log("\u{1F389} [OpenFront Channel] Order created successfully:", order.id); + const processedLineItems = cartItems.map((item) => ({ + id: item.variantId, + title: item.name || `Product ${item.variantId}`, quantity: item.quantity, - variantId: item.productVariant.id, - productId: item.productVariant.product.id + variantId: item.variantId })); return { purchaseId: order.id, - orderNumber: order.orderNumber, - totalPrice: (order.total / 100).toFixed(2), + orderNumber: `#${order.displayId}`, + totalPrice: order.total, invoiceUrl: `https://${platform.domain}/admin/orders/${order.id}`, lineItems: processedLineItems, - status: "processing" + status: "pending" }; } catch (error) { - console.error("OpenFront Channel: Purchase creation failed:", error); + console.error("\u{1F6A8} OpenFront Channel: Purchase creation failed:", error); + if (error.response?.errors) { + console.error("\u{1F6A8} GraphQL Errors:"); + error.response.errors.forEach((err, i) => { + console.error(` ${i + 1}. ${err.message}`); + if (err.path) { + console.error(` Path: ${err.path.join(" -> ")}`); + } + if (err.extensions) { + console.error(` Extensions:`, err.extensions); + } + }); + } return { - purchaseId, - orderNumber, - totalPrice: totalPrice.toFixed(2), + purchaseId: null, + orderNumber: null, + totalPrice: "0.00", invoiceUrl: null, lineItems: cartItems.map((item) => ({ id: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, @@ -314,51 +384,123 @@ async function createWebhookFunction({ endpoint, events }) { - const openFrontClient = await createOpenFrontClient(platform); - const createWebhookMutation = import_graphql_request.gql` - mutation CreateChannelWebhookEndpoint($data: WebhookEndpointCreateInput!) { - createWebhookEndpoint(data: $data) { - id - url - events - isActive - secret + console.log("\u{1FA9D} [OpenFront Channel] createWebhookFunction called"); + console.log("\u{1FA9D} [OpenFront Channel] Platform domain:", platform.domain); + console.log("\u{1FA9D} [OpenFront Channel] Endpoint URL:", endpoint); + console.log("\u{1FA9D} [OpenFront Channel] Events received:", events); + console.log("\u{1FA9D} [OpenFront Channel] Events type:", typeof events, "Array?", Array.isArray(events)); + console.log("\u{1FA9D} [OpenFront Channel] Platform data:", JSON.stringify(platform, null, 2)); + const eventMap = { + ORDER_CREATED: "order.created", + ORDER_CANCELLED: "order.cancelled", + TRACKING_CREATED: "fulfillment.created" + }; + const openFrontEvents = events.map((event) => { + const mapped = eventMap[event] || event; + console.log(`\u{1FA9D} [OpenFront Channel] Mapping: ${event} -> ${mapped}`); + return mapped; + }); + console.log("\u{1FA9D} [OpenFront Channel] Final mapped events array:", openFrontEvents); + console.log("\u{1FA9D} [OpenFront Channel] Joined events string:", openFrontEvents.join(", ")); + try { + console.log("\u{1FA9D} [OpenFront Channel] Creating OpenFront GraphQL client..."); + const openFrontClient = await createOpenFrontClient(platform); + console.log("\u2705 [OpenFront Channel] GraphQL client created successfully"); + console.log("\u{1FA9D} [OpenFront Channel] Fetching current user..."); + const getUserQuery = import_graphql_request.gql` + query GetCurrentUser { + authenticatedItem { + ... on User { + id + email + orderWebhookUrl + } + } + } + `; + console.log("\u{1FA9D} [OpenFront Channel] Executing getUserQuery..."); + const { authenticatedItem: user } = await openFrontClient.request(getUserQuery); + console.log("\u{1FA9D} [OpenFront Channel] getUserQuery result:", JSON.stringify(user, null, 2)); + if (!user) { + console.error("\u{1F6A8} [OpenFront Channel] User not authenticated - authenticatedItem is null/undefined"); + throw new Error("User not authenticated"); + } + console.log("\u2705 [OpenFront Channel] User authenticated successfully"); + console.log("\u{1FA9D} [OpenFront Channel] User ID:", user.id); + console.log("\u{1FA9D} [OpenFront Channel] User email:", user.email); + console.log("\u{1FA9D} [OpenFront Channel] Current webhook URL:", user.orderWebhookUrl); + console.log("\u{1FA9D} [OpenFront Channel] Updating user webhook URL..."); + const updateUserMutation = import_graphql_request.gql` + mutation UpdateActiveUserWebhookUrl($data: UserUpdateProfileInput!) { + updateActiveUser(data: $data) { + id + orderWebhookUrl + } + } + `; + console.log("\u{1FA9D} [OpenFront Channel] Update mutation variables:"); + console.log("\u{1FA9D} [OpenFront Channel] - User ID:", user.id); + console.log("\u{1FA9D} [OpenFront Channel] - New webhook URL:", endpoint); + const result = await openFrontClient.request(updateUserMutation, { + data: { orderWebhookUrl: endpoint } + }); + console.log("\u{1FA9D} [OpenFront Channel] Update mutation result:", JSON.stringify(result, null, 2)); + const updatedUser = result.updateActiveUser; + console.log("\u2705 [OpenFront Channel] User webhook URL updated successfully"); + console.log("\u{1FA9D} [OpenFront Channel] Updated user ID:", updatedUser.id); + console.log("\u{1FA9D} [OpenFront Channel] Updated webhook URL:", updatedUser.orderWebhookUrl); + const webhookResponse = { + webhooks: [{ + id: `user-${updatedUser.id}`, + callbackUrl: updatedUser.orderWebhookUrl, + topic: openFrontEvents.join(", "), + // Join array into comma-separated string + format: "JSON", + createdAt: (/* @__PURE__ */ new Date()).toISOString() + }], + webhookId: `user-${updatedUser.id}` + }; + console.log("\u{1FA9D} [OpenFront Channel] Final webhook response:", JSON.stringify(webhookResponse, null, 2)); + return webhookResponse; + } catch (error) { + console.error("\u{1F6A8} [OpenFront Channel] createWebhookFunction failed:", error); + console.error("\u{1F6A8} [OpenFront Channel] Error message:", error.message); + console.error("\u{1F6A8} [OpenFront Channel] Error stack:", error.stack); + if (error.response) { + console.error("\u{1F6A8} [OpenFront Channel] GraphQL response:", JSON.stringify(error.response, null, 2)); + if (error.response.errors) { + console.error("\u{1F6A8} [OpenFront Channel] GraphQL errors:"); + error.response.errors.forEach((err, i) => { + console.error(`\u{1F6A8} [OpenFront Channel] ${i + 1}. ${err.message}`); + if (err.path) { + console.error(`\u{1F6A8} [OpenFront Channel] Path: ${err.path.join(" -> ")}`); + } + if (err.extensions) { + console.error(`\u{1F6A8} [OpenFront Channel] Extensions:`, err.extensions); + } + }); } } - `; - const eventMap = { - PURCHASE_CREATED: "order.created", - PURCHASE_SHIPPED: "fulfillment.shipped", - INVENTORY_UPDATED: "inventory.updated" - }; - const openFrontEvents = events.map((event) => eventMap[event] || event); - const result = await openFrontClient.request(createWebhookMutation, { - data: { - url: endpoint, - events: openFrontEvents, - isActive: true - } - }); - const webhook = result.createWebhookEndpoint; - return { - webhooks: [webhook], - webhookId: webhook.id - }; + throw error; + } } async function deleteWebhookFunction({ platform, webhookId }) { const openFrontClient = await createOpenFrontClient(platform); - const deleteWebhookMutation = import_graphql_request.gql` - mutation DeleteChannelWebhookEndpoint($where: WebhookEndpointWhereUniqueInput!) { - deleteWebhookEndpoint(where: $where) { + const userId = webhookId.replace("user-", ""); + const updateUserMutation = import_graphql_request.gql` + mutation ClearUserWebhookUrl($where: UserWhereUniqueInput!, $data: UserUpdateInput!) { + updateUser(where: $where, data: $data) { id + orderWebhookUrl } } `; - const result = await openFrontClient.request(deleteWebhookMutation, { - where: { id: webhookId } + const result = await openFrontClient.request(updateUserMutation, { + where: { id: userId }, + data: { orderWebhookUrl: null } }); return result; } @@ -366,30 +508,34 @@ async function getWebhooksFunction({ platform }) { const openFrontClient = await createOpenFrontClient(platform); - const query = import_graphql_request.gql` - query GetChannelWebhookEndpoints { - webhookEndpoints(where: { isActive: { equals: true } }) { - id - url - events - isActive - createdAt + const eventMap = { + "order.created": "PURCHASE_CREATED", + "fulfillment.created": "PURCHASE_SHIPPED" + }; + const getUserQuery = import_graphql_request.gql` + query GetCurrentUser { + authenticatedItem { + ... on User { + id + email + orderWebhookUrl + createdAt + } } } `; - const { webhookEndpoints } = await openFrontClient.request(query); - const eventMap = { - "order.created": "PURCHASE_CREATED", - "fulfillment.shipped": "PURCHASE_SHIPPED", - "inventory.updated": "INVENTORY_UPDATED" - }; - const webhooks = webhookEndpoints.map((webhook) => ({ - id: webhook.id, - callbackUrl: webhook.url, - topic: webhook.events.map((event) => eventMap[event] || event), + const { authenticatedItem: user } = await openFrontClient.request(getUserQuery); + if (!user || !user.orderWebhookUrl) { + return { webhooks: [] }; + } + const webhooks = [{ + id: `user-${user.id}`, + callbackUrl: user.orderWebhookUrl, + topic: ["PURCHASE_CREATED", "PURCHASE_SHIPPED"], + // These are the channel events we support format: "JSON", - createdAt: webhook.createdAt - })); + createdAt: user.createdAt + }]; return { webhooks }; } async function addTrackingFunction({ @@ -501,41 +647,119 @@ async function oAuthCallbackFunction({ console.error("OpenFront OAuth error:", errorText); throw new Error(`Failed to exchange OAuth code for access token: ${response.statusText}`); } - const { access_token } = await response.json(); - return access_token; + const { access_token, refresh_token, expires_in } = await response.json(); + return { + accessToken: access_token, + refreshToken: refresh_token, + expiresIn: expires_in, + tokenExpiresAt: new Date(Date.now() + expires_in * 1e3).toISOString() + }; } function scopes() { return REQUIRED_SCOPES; } -var import_graphql_request, getFreshAccessToken, createOpenFrontClient, getProductImageUrl, REQUIRED_SCOPES; +var import_graphql_request, import_context, getFreshAccessToken, createOpenFrontClient, getProductImageUrl, REQUIRED_SCOPES; var init_openfront = __esm({ "features/integrations/channel/openfront.ts"() { "use strict"; import_graphql_request = require("graphql-request"); + import_context = require("@/features/keystone/context"); getFreshAccessToken = async (platform) => { - if (platform.tokenExpiresAt && platform.refreshToken) { - const expiresAt = typeof platform.tokenExpiresAt === "string" ? new Date(platform.tokenExpiresAt) : platform.tokenExpiresAt; - if (expiresAt > /* @__PURE__ */ new Date()) { + console.log("\u{1F504} [OpenFront Channel] getFreshAccessToken called"); + console.log("\u{1F504} [OpenFront Channel] Platform domain:", platform.domain); + console.log("\u{1F504} [OpenFront Channel] Actual access token:", platform.accessToken); + const channels = await import_context.keystoneContext.sudo().query.Channel.findMany({ + where: { + domain: { equals: platform.domain }, + accessToken: { equals: platform.accessToken } + }, + query: "id refreshToken tokenExpiresAt platform { appKey appSecret }" + }); + if (!channels || channels.length === 0) { + console.log("\u26A0\uFE0F [OpenFront Channel] No matching channel found in database"); + return platform.accessToken; + } + const channel = channels[0]; + console.log("\u{1F504} [OpenFront Channel] Found channel:", channel.id); + console.log("\u{1F504} [OpenFront Channel] Has refresh token:", !!channel.refreshToken); + console.log("\u{1F504} [OpenFront Channel] Token expires at:", channel.tokenExpiresAt); + console.log("\u{1F504} [OpenFront Channel] Has appKey:", !!channel.platform?.appKey); + console.log("\u{1F504} [OpenFront Channel] Has appSecret:", !!channel.platform?.appSecret); + console.log("\u{1F504} [OpenFront Channel] Actual refresh token:", channel.refreshToken); + if (channel.refreshToken) { + console.log("\u{1F504} [OpenFront Channel] Refresh token found, checking if refresh needed"); + let shouldRefresh = false; + if (channel.tokenExpiresAt) { + const expiresAt = typeof channel.tokenExpiresAt === "string" ? new Date(channel.tokenExpiresAt) : channel.tokenExpiresAt; + const now = /* @__PURE__ */ new Date(); + shouldRefresh = expiresAt <= now; + console.log("\u{1F504} [OpenFront Channel] Token expiry check:"); + console.log("\u{1F504} [OpenFront Channel] - Expires at:", expiresAt.toISOString()); + console.log("\u{1F504} [OpenFront Channel] - Current time:", now.toISOString()); + console.log("\u{1F504} [OpenFront Channel] - Should refresh:", shouldRefresh); + } else { + shouldRefresh = true; + console.log("\u{1F504} [OpenFront Channel] No expiry info found, assuming refresh needed"); + } + if (shouldRefresh) { + console.log("\u{1F504} [OpenFront Channel] Starting token refresh process..."); + const tokenUrl = `${platform.domain}/api/oauth/token`; + console.log("\u{1F504} [OpenFront Channel] Token URL:", tokenUrl); + const formData = new URLSearchParams({ + grant_type: "refresh_token", + refresh_token: channel.refreshToken, + client_id: channel.platform?.appKey || "", + client_secret: channel.platform?.appSecret || "" + }); + console.log("\u{1F504} [OpenFront Channel] Refresh request params:"); + console.log("\u{1F504} [OpenFront Channel] - grant_type: refresh_token"); + console.log("\u{1F504} [OpenFront Channel] - client_id:", channel.platform?.appKey || "NOT_SET"); + console.log("\u{1F504} [OpenFront Channel] - client_secret:", channel.platform?.appSecret ? "SET" : "NOT_SET"); + console.log("\u{1F504} [OpenFront Channel] - refresh_token:", channel.refreshToken ? "SET" : "NOT_SET"); + console.log("\u{1F504} [OpenFront Channel] Making refresh token request..."); + const response = await fetch(tokenUrl, { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: formData + }); + console.log("\u{1F504} [OpenFront Channel] Refresh response status:", response.status); + console.log("\u{1F504} [OpenFront Channel] Refresh response ok:", response.ok); + if (!response.ok) { + const errorText = await response.text(); + console.error("\u{1F6A8} [OpenFront Channel] Token refresh failed:", errorText); + console.error("\u{1F6A8} [OpenFront Channel] Response status:", response.status); + console.error("\u{1F6A8} [OpenFront Channel] Response statusText:", response.statusText); + throw new Error(`Failed to refresh access token: ${response.statusText} - ${errorText}`); + } + const tokenData = await response.json(); + console.log("\u{1F504} [OpenFront Channel] Token refresh response received"); + console.log("\u{1F504} [OpenFront Channel] - Has access_token:", !!tokenData.access_token); + console.log("\u{1F504} [OpenFront Channel] - Has refresh_token:", !!tokenData.refresh_token); + console.log("\u{1F504} [OpenFront Channel] - Expires in:", tokenData.expires_in, "seconds"); + const { access_token, refresh_token, expires_in } = tokenData; + console.log("\u{1F504} [OpenFront Channel] Updating tokens in database..."); + try { + console.log("\u{1F504} [OpenFront Channel] Updating channel:", channel.id); + await import_context.keystoneContext.sudo().query.Channel.updateOne({ + where: { id: channel.id }, + data: { + accessToken: access_token, + ...refresh_token && { refreshToken: refresh_token }, + ...expires_in && { tokenExpiresAt: new Date(Date.now() + expires_in * 1e3) } + } + }); + console.log("\u2705 [OpenFront Channel] Channel updated with new tokens:", channel.id); + } catch (error) { + console.error("\u{1F6A8} [OpenFront Channel] Failed to update channel tokens in database:", error); + } + console.log("\u2705 [OpenFront Channel] Returning fresh access token"); + return access_token; + } else { + console.log("\u2705 [OpenFront Channel] Token still valid, using existing access token"); return platform.accessToken; } - const tokenUrl = `${platform.domain}/api/oauth/token`; - const formData = new URLSearchParams({ - grant_type: "refresh_token", - refresh_token: platform.refreshToken - }); - const response = await fetch(tokenUrl, { - method: "POST", - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - body: formData - }); - if (!response.ok) { - const errorText = await response.text(); - console.error("Token refresh failed:", errorText); - throw new Error(`Failed to refresh access token: ${response.statusText} - ${errorText}`); - } - const { access_token } = await response.json(); - return access_token; } + console.log("\u26A0\uFE0F [OpenFront Channel] No refresh token available, using existing access token"); return platform.accessToken; }; createOpenFrontClient = async (platform) => { @@ -1430,6 +1654,7 @@ async function searchOrdersFunction({ searchEntry, after }) { + console.log("fuckkk"); const openFrontClient = await createOpenFrontClient2(platform); const gqlQuery = import_graphql_request3.gql` query SearchOrders($where: OrderWhereInput, $take: Int, $skip: Int) { @@ -1511,6 +1736,7 @@ async function searchOrdersFunction({ take, skip }); + console.log("Orders from OpenFront:", orders); const transformedOrders = orders.map((order) => { const shippingAddress = order.shippingAddress || {}; return { @@ -1531,22 +1757,28 @@ async function searchOrdersFunction({ financialStatus: order.status, totalPrice: order.rawTotal ? (order.rawTotal / 100).toFixed(2) : "0.00", currency: order.currency?.code || "USD", - lineItems: (order.lineItems || []).map((lineItem) => ({ - lineItemId: lineItem.id, - name: lineItem.title, - quantity: lineItem.quantity, - image: getProductImageUrl2({ imagePath: lineItem.thumbnail, image: { url: lineItem.productVariant?.product?.thumbnail } }, platform.domain) || "", - price: lineItem.moneyAmount ? (lineItem.moneyAmount.amount / 100).toFixed(2) : "0.00", - variantId: lineItem.productVariant?.id || "", - productId: lineItem.productVariant?.product?.id || "", - sku: lineItem.sku || lineItem.productVariant?.sku || "" - })), + lineItems: (order.lineItems || []).map((lineItem) => { + const productTitle = lineItem.productVariant?.product?.title || ""; + const variantTitle = lineItem.productVariant?.title || ""; + const combinedTitle = productTitle && variantTitle ? `${productTitle} - ${variantTitle}` : lineItem.title; + return { + lineItemId: lineItem.id, + name: combinedTitle, + quantity: lineItem.quantity, + image: getProductImageUrl2({ imagePath: lineItem.thumbnail, image: { url: lineItem.productVariant?.product?.thumbnail } }, platform.domain) || "", + price: lineItem.moneyAmount ? (lineItem.moneyAmount.amount / 100).toFixed(2) : "0.00", + variantId: lineItem.productVariant?.id || "", + productId: lineItem.productVariant?.product?.id || "", + sku: lineItem.sku || lineItem.productVariant?.sku || "" + }; + }), cartItems: [], fulfillments: [], note: "", cursor: Buffer.from((skip + orders.indexOf(order) + 1).toString()).toString("base64") }; }); + console.log("Transformed orders:", transformedOrders); const hasNextPage = skip + take < ordersCount; const endCursor = hasNextPage ? Buffer.from((skip + take).toString()).toString("base64") : null; return { @@ -1719,10 +1951,10 @@ async function oAuthCallbackFunction3({ } const { access_token, refresh_token, expires_in } = await response.json(); return { - access_token, - refresh_token, - expires_in, - expires_at: new Date(Date.now() + expires_in * 1e3) + accessToken: access_token, + refreshToken: refresh_token, + expiresIn: expires_in, + tokenExpiresAt: new Date(Date.now() + expires_in * 1e3).toISOString() }; } async function createOrderWebhookHandler({ @@ -1730,41 +1962,51 @@ async function createOrderWebhookHandler({ event, headers }) { - const signature = headers["x-openfront-webhook-signature"]; + const signature = headers["x-openfront-webhook-signature"] || headers["X-OpenFront-Webhook-Signature"]; if (!signature) { + console.error("Missing webhook signature. Available headers:", Object.keys(headers)); throw new Error("Missing webhook signature"); } - const lineItemsOutput = event.data?.orderLineItems?.map((item) => ({ - name: item.title, - image: getProductImageUrl2(item.productVariant?.product?.productImages?.[0], platform.domain), - price: item.unitPrice ? item.unitPrice / 100 : 0, - // Convert from cents, handle null/undefined - quantity: item.quantity || 0, - productId: item.productVariant?.product?.id, - variantId: item.productVariant?.id, - sku: item.productVariant?.sku || "", - lineItemId: item.id - })) || []; + const lineItemsOutput = event.data?.lineItems?.map((item) => { + const productTitle = item.productVariant?.product?.title || ""; + const variantTitle = item.productVariant?.title || ""; + const combinedTitle = productTitle && variantTitle ? `${productTitle} - ${variantTitle}` : item.title; + return { + name: combinedTitle, + image: getProductImageUrl2(item.productVariant?.product?.productImages?.[0], platform.domain) || item.thumbnail, + price: item.moneyAmount?.amount ? item.moneyAmount.amount / 100 : 0, + // Convert from cents to float + quantity: item.quantity || 0, + productId: item.productVariant?.product?.id?.toString(), + variantId: item.productVariant?.id?.toString(), + sku: item.productVariant?.sku || item.sku || "", + lineItemId: item.id?.toString() + }; + }) || []; const orderData = event.data; + const shippingAddress = orderData.shippingAddress || {}; return { - orderId: orderData.id, - orderName: orderData.orderNumber, - email: orderData.customerEmail, - firstName: orderData.firstName, - lastName: orderData.lastName, - streetAddress1: orderData.address1, - streetAddress2: orderData.address2, - city: orderData.city, - state: orderData.state, - zip: orderData.postalCode, - country: orderData.countryCode, - phone: orderData.phone, - currency: orderData.currency?.code || "USD", - totalPrice: orderData.total ? orderData.total / 100 : 0, - // Convert from cents, handle null/undefined - subTotalPrice: orderData.subtotal || orderData.total ? (orderData.subtotal || orderData.total) / 100 : 0, - totalDiscounts: orderData.totalDiscounts ? orderData.totalDiscounts / 100 : 0, - totalTax: orderData.totalTax ? orderData.totalTax / 100 : 0, + orderId: orderData.id?.toString(), + orderName: orderData.displayId ? `#${orderData.displayId}` : "", + email: orderData.email || "", + firstName: shippingAddress.firstName || "", + lastName: shippingAddress.lastName || "", + streetAddress1: shippingAddress.address1 || "", + streetAddress2: shippingAddress.address2 || "", + city: shippingAddress.city || "", + state: shippingAddress.province || "", + zip: shippingAddress.postalCode || "", + country: shippingAddress.country?.iso2?.toUpperCase() || "", + phone: shippingAddress.phone || "", + currency: orderData.currency?.code?.toUpperCase() || "USD", + totalPrice: orderData.rawTotal ? orderData.rawTotal / 100 : 0, + // rawTotal is in cents, convert to float + subTotalPrice: parseFloat(orderData.subtotal?.replace(/[$,]/g, "") || "0"), + // Parse formatted string to float + totalDiscounts: parseFloat(orderData.discount?.replace(/[$,]/g, "") || "0"), + // Parse formatted string to float + totalTax: parseFloat(orderData.tax?.replace(/[$,]/g, "") || "0"), + // Parse formatted string to float status: "INPROCESS", linkOrder: true, matchOrder: true, @@ -1822,36 +2064,109 @@ async function addTrackingFunction2({ }); return result; } -var import_graphql_request3, import_getBaseUrl, getFreshAccessToken2, createOpenFrontClient2, getProductImageUrl2, REQUIRED_SCOPES3; +var import_graphql_request3, import_getBaseUrl, import_context2, getFreshAccessToken2, createOpenFrontClient2, getProductImageUrl2, REQUIRED_SCOPES3; var init_openfront2 = __esm({ "features/integrations/shop/openfront.ts"() { "use strict"; import_graphql_request3 = require("graphql-request"); import_getBaseUrl = require("@/features/dashboard/lib/getBaseUrl"); + import_context2 = require("@/features/keystone/context"); getFreshAccessToken2 = async (platform) => { - if (platform.tokenExpiresAt && platform.refreshToken) { - const expiresAt = typeof platform.tokenExpiresAt === "string" ? new Date(platform.tokenExpiresAt) : platform.tokenExpiresAt; - if (expiresAt > /* @__PURE__ */ new Date()) { + console.log("\u{1F504} [OpenFront Shop] getFreshAccessToken called"); + console.log("\u{1F504} [OpenFront Shop] Platform domain:", platform.domain); + console.log("\u{1F504} [OpenFront Shop] Actual access token:", platform.accessToken); + const shops = await import_context2.keystoneContext.sudo().query.Shop.findMany({ + where: { + domain: { equals: platform.domain }, + accessToken: { equals: platform.accessToken } + }, + query: "id refreshToken tokenExpiresAt platform { appKey appSecret }" + }); + if (!shops || shops.length === 0) { + console.log("\u26A0\uFE0F [OpenFront Shop] No matching shop found in database"); + return platform.accessToken; + } + const shop = shops[0]; + console.log("\u{1F504} [OpenFront Shop] Found shop:", shop.id); + console.log("\u{1F504} [OpenFront Shop] Has refresh token:", !!shop.refreshToken); + console.log("\u{1F504} [OpenFront Shop] Token expires at:", shop.tokenExpiresAt); + console.log("\u{1F504} [OpenFront Shop] Has appKey:", !!shop.platform?.appKey); + console.log("\u{1F504} [OpenFront Shop] Has appSecret:", !!shop.platform?.appSecret); + console.log("\u{1F504} [OpenFront Shop] Actual refresh token:", shop.refreshToken); + if (shop.refreshToken) { + console.log("\u{1F504} [OpenFront Shop] Refresh token found, checking if refresh needed"); + let shouldRefresh = false; + if (shop.tokenExpiresAt) { + const expiresAt = typeof shop.tokenExpiresAt === "string" ? new Date(shop.tokenExpiresAt) : shop.tokenExpiresAt; + const now = /* @__PURE__ */ new Date(); + shouldRefresh = expiresAt <= now; + console.log("\u{1F504} [OpenFront Shop] Token expiry check:"); + console.log("\u{1F504} [OpenFront Shop] - Expires at:", expiresAt.toISOString()); + console.log("\u{1F504} [OpenFront Shop] - Current time:", now.toISOString()); + console.log("\u{1F504} [OpenFront Shop] - Should refresh:", shouldRefresh); + } else { + shouldRefresh = true; + console.log("\u{1F504} [OpenFront Shop] No expiry info found, assuming refresh needed"); + } + if (shouldRefresh) { + console.log("\u{1F504} [OpenFront Shop] Starting token refresh process..."); + const tokenUrl = `${platform.domain}/api/oauth/token`; + console.log("\u{1F504} [OpenFront Shop] Token URL:", tokenUrl); + const formData = new URLSearchParams({ + grant_type: "refresh_token", + refresh_token: shop.refreshToken, + client_id: shop.platform?.appKey || "", + client_secret: shop.platform?.appSecret || "" + }); + console.log("\u{1F504} [OpenFront Shop] Refresh request params:"); + console.log("\u{1F504} [OpenFront Shop] - grant_type: refresh_token"); + console.log("\u{1F504} [OpenFront Shop] - client_id:", shop.platform?.appKey || "NOT_SET"); + console.log("\u{1F504} [OpenFront Shop] - client_secret:", shop.platform?.appSecret ? "SET" : "NOT_SET"); + console.log("\u{1F504} [OpenFront Shop] - refresh_token:", shop.refreshToken ? "SET" : "NOT_SET"); + console.log("\u{1F504} [OpenFront Shop] Making refresh token request..."); + const response = await fetch(tokenUrl, { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: formData + }); + console.log("\u{1F504} [OpenFront Shop] Refresh response status:", response.status); + console.log("\u{1F504} [OpenFront Shop] Refresh response ok:", response.ok); + if (!response.ok) { + const errorText = await response.text(); + console.error("\u{1F6A8} [OpenFront Shop] Token refresh failed:", errorText); + console.error("\u{1F6A8} [OpenFront Shop] Response status:", response.status); + console.error("\u{1F6A8} [OpenFront Shop] Response statusText:", response.statusText); + throw new Error(`Failed to refresh access token: ${response.statusText} - ${errorText}`); + } + const tokenData = await response.json(); + console.log("\u{1F504} [OpenFront Shop] Token refresh response received"); + console.log("\u{1F504} [OpenFront Shop] - Has access_token:", !!tokenData.access_token); + console.log("\u{1F504} [OpenFront Shop] - Has refresh_token:", !!tokenData.refresh_token); + console.log("\u{1F504} [OpenFront Shop] - Expires in:", tokenData.expires_in, "seconds"); + const { access_token, refresh_token, expires_in } = tokenData; + console.log("\u{1F504} [OpenFront Shop] Updating tokens in database..."); + try { + console.log("\u{1F504} [OpenFront Shop] Updating shop:", shop.id); + await import_context2.keystoneContext.sudo().query.Shop.updateOne({ + where: { id: shop.id }, + data: { + accessToken: access_token, + ...refresh_token && { refreshToken: refresh_token }, + ...expires_in && { tokenExpiresAt: new Date(Date.now() + expires_in * 1e3) } + } + }); + console.log("\u2705 [OpenFront Shop] Shop updated with new tokens:", shop.id); + } catch (error) { + console.error("\u{1F6A8} [OpenFront Shop] Failed to update shop tokens in database:", error); + } + console.log("\u2705 [OpenFront Shop] Returning fresh access token"); + return access_token; + } else { + console.log("\u2705 [OpenFront Shop] Token still valid, using existing access token"); return platform.accessToken; } - const tokenUrl = `${platform.domain}/api/oauth/token`; - const formData = new URLSearchParams({ - grant_type: "refresh_token", - refresh_token: platform.refreshToken - }); - const response = await fetch(tokenUrl, { - method: "POST", - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - body: formData - }); - if (!response.ok) { - const errorText = await response.text(); - console.error("Token refresh failed:", errorText); - throw new Error(`Failed to refresh access token: ${response.statusText} - ${errorText}`); - } - const { access_token } = await response.json(); - return access_token; } + console.log("\u26A0\uFE0F [OpenFront Shop] No refresh token available, using existing access token"); return platform.accessToken; }; createOpenFrontClient2 = async (platform) => { @@ -3721,6 +4036,7 @@ async function placeMultipleOrders({ ids, query }) { zip, country, phone, + currency, user, shop, orderId: shopOrderId, @@ -3738,7 +4054,8 @@ async function placeMultipleOrders({ ids, query }) { state, zip, country, - phone + phone, + currency shop { domain accessToken @@ -3826,7 +4143,8 @@ async function placeMultipleOrders({ ids, query }) { zip, country, phone, - email: user.email + email: user.email, + currency }, notes: "" }); @@ -6103,8 +6421,8 @@ var ShopPlatform = (0, import_core18.list)({ label: "App Credentials", description: "Adding these fields will enable this platform to be installed as an app by users", fields: { - appKey: (0, import_fields17.text)({ validation: { isRequired: true } }), - appSecret: (0, import_fields17.text)({ validation: { isRequired: true } }), + appKey: (0, import_fields17.text)(), + appSecret: (0, import_fields17.text)(), callbackUrl: (0, import_fields17.virtual)({ field: import_core18.graphql.field({ type: import_core18.graphql.String, @@ -6204,8 +6522,8 @@ var ChannelPlatform = (0, import_core19.list)({ label: "App Credentials", description: "Adding these fields will enable this platform to be installed as an app by users.", fields: { - appKey: (0, import_fields18.text)({ validation: { isRequired: true } }), - appSecret: (0, import_fields18.text)({ validation: { isRequired: true } }), + appKey: (0, import_fields18.text)(), + appSecret: (0, import_fields18.text)(), callbackUrl: (0, import_fields18.virtual)({ field: import_core19.graphql.field({ type: import_core19.graphql.String, @@ -7363,7 +7681,6 @@ function statelessSessions({ async get({ context }) { if (!context?.req) return; const authHeader = context.req.headers.authorization; - console.log("\u{1F511} AUTH HEADER:", authHeader); if (authHeader?.startsWith("Bearer ")) { const accessToken = authHeader.replace("Bearer ", ""); console.log("\u{1F511} ACCESS TOKEN:", accessToken); diff --git a/.keystone/config.js.map b/.keystone/config.js.map index 996a2c9..e1c776f 100644 --- a/.keystone/config.js.map +++ b/.keystone/config.js.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../features/integrations/channel/openfront.ts", "../features/integrations/channel/shopify.ts", "../features/integrations/channel/lib/executor.ts", "../features/integrations/shop/openfront.ts", "../features/integrations/shop/shopify.ts", "../features/integrations/shop/lib/executor.ts", "../keystone.ts", "../features/keystone/index.ts", "../features/keystone/models/User.ts", "../features/keystone/lib/api-key-scopes.ts", "../features/keystone/access.ts", "../features/keystone/models/trackingFields.ts", "../features/keystone/models/ApiKey.ts", "../features/keystone/models/Role.ts", "../features/keystone/models/fields.ts", "../features/keystone/models/Order.ts", "../features/keystone/utils/channelProviderAdapter.ts", "../features/keystone/utils/shopProviderAdapter.ts", "../features/keystone/lib/placeMultipleOrders.ts", "../features/keystone/extendGraphqlSchema/mutations/addMatchToCart.ts", "../features/keystone/models/TrackingDetail.ts", "../features/keystone/models/LineItem.ts", "../features/keystone/models/CartItem.ts", "../features/keystone/models/Channel.ts", "../features/keystone/models/ChannelItem.ts", "../features/keystone/extendGraphqlSchema/queries/getMatchQuery.ts", "../features/keystone/extendGraphqlSchema/queries/getMatchCount.ts", "../features/keystone/extendGraphqlSchema/queries/getShopWebhooks.ts", "../features/keystone/extendGraphqlSchema/mutations/redirectToInit.ts", "../features/keystone/extendGraphqlSchema/queries/searchShopOrders.ts", "../features/keystone/extendGraphqlSchema/queries/searchShopProducts.ts", "../features/keystone/extendGraphqlSchema/queries/searchChannelProducts.ts", "../features/keystone/extendGraphqlSchema/queries/getChannelWebhooks.ts", "../features/keystone/extendGraphqlSchema/queries/getFilteredMatches.ts", "../features/keystone/extendGraphqlSchema/queries/getChannelProduct.ts", "../features/keystone/extendGraphqlSchema/queries/getShopProduct.ts", "../features/keystone/models/Shop.ts", "../features/keystone/models/ShopItem.ts", "../features/keystone/models/Match.ts", "../features/keystone/models/Link.ts", "../features/keystone/models/ShopPlatform.ts", "../features/keystone/models/ChannelPlatform.ts", "../features/keystone/models/index.ts", "../features/keystone/extendGraphqlSchema/index.ts", "../features/keystone/extendGraphqlSchema/mutations/addToCart.ts", "../features/keystone/extendGraphqlSchema/mutations/cancelOrder.ts", "../features/keystone/extendGraphqlSchema/mutations/cancelPurchase.ts", "../features/keystone/extendGraphqlSchema/mutations/matchOrder.ts", "../features/keystone/extendGraphqlSchema/mutations/overwriteMatch.ts", "../features/keystone/extendGraphqlSchema/mutations/placeOrders.ts", "../features/keystone/extendGraphqlSchema/mutations/createShopWebhook.ts", "../features/keystone/extendGraphqlSchema/mutations/deleteShopWebhook.ts", "../features/keystone/extendGraphqlSchema/mutations/updateShopProduct.ts", "../features/keystone/extendGraphqlSchema/mutations/createChannelWebhook.ts", "../features/keystone/extendGraphqlSchema/mutations/deleteChannelWebhook.ts", "../features/keystone/extendGraphqlSchema/mutations/createChannelPurchase.ts", "../features/keystone/extendGraphqlSchema/mutations/upsertMatch.ts", "../features/keystone/lib/mail.ts"], - "sourcesContent": ["import { GraphQLClient, gql } from \"graphql-request\";\n\ninterface OpenFrontPlatform {\n domain: string;\n accessToken: string;\n refreshToken?: string;\n tokenExpiresAt?: Date | string;\n appKey?: string;\n appSecret?: string;\n}\n\ninterface SearchProductsArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface GetProductArgs {\n productId: string;\n variantId?: string;\n}\n\ninterface CreatePurchaseArgs {\n cartItems: any[];\n shipping: any;\n notes?: string;\n}\n\ninterface CreateWebhookArgs {\n endpoint: string;\n events: string[];\n}\n\ninterface DeleteWebhookArgs {\n webhookId: string;\n}\n\n// Helper function to get fresh access token with proper OAuth 2.0 flow\nconst getFreshAccessToken = async (platform: OpenFrontPlatform) => {\n // Check if we have local access token expiry information\n if (platform.tokenExpiresAt && platform.refreshToken) {\n const expiresAt = typeof platform.tokenExpiresAt === 'string' \n ? new Date(platform.tokenExpiresAt) \n : platform.tokenExpiresAt;\n \n // If access token hasn't expired yet, use it\n if (expiresAt > new Date()) {\n return platform.accessToken;\n }\n \n // Use refresh token to get new access token\n const tokenUrl = `${platform.domain}/api/oauth/token`;\n \n const formData = new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: platform.refreshToken,\n });\n\n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: formData,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('Token refresh failed:', errorText);\n throw new Error(`Failed to refresh access token: ${response.statusText} - ${errorText}`);\n }\n\n const { access_token } = await response.json();\n \n // TODO: Update stored access token and expiry in database\n // This would require updating the shop/channel record with new tokens\n \n return access_token;\n }\n \n // If no refresh capability, just use the access token as-is\n return platform.accessToken;\n};\n\n// Helper function to create OpenFront GraphQL client with fresh token\nconst createOpenFrontClient = async (platform: OpenFrontPlatform) => {\n const freshAccessToken = await getFreshAccessToken(platform);\n\n return new GraphQLClient(\n `${platform.domain}/api/graphql`,\n {\n headers: {\n \"Authorization\": `Bearer ${freshAccessToken}`,\n \"Content-Type\": \"application/json\",\n },\n }\n );\n};\n\n// Helper function to get product image URL\n// imagePath is a relative path (e.g., \"/images/product.jpg\") that needs domain prepended\n// image.url is an absolute S3 URL that can be used directly\nconst getProductImageUrl = (productImage: any, domain: string): string | null => {\n if (productImage?.imagePath) {\n return `${domain}${productImage.imagePath}`;\n }\n return productImage?.image?.url || null;\n};\n\n// Function to search products for fulfillment\nexport async function searchProductsFunction({ \n platform, \n searchEntry, \n after \n}: { \n platform: OpenFrontPlatform; \n searchEntry: string; \n after?: string; \n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const gqlQuery = gql`\n query SearchChannelProducts($where: ProductWhereInput, $take: Int, $skip: Int) {\n products(where: $where, take: $take, skip: $skip, orderBy: { createdAt: desc }) {\n id\n title\n handle\n productImages {\n image {\n url\n }\n imagePath\n }\n productVariants {\n id\n title\n sku\n inventoryQuantity\n prices {\n id\n amount\n currency {\n code\n }\n }\n }\n status\n }\n productsCount(where: $where)\n }\n `;\n\n // Build search filter - only show products available for fulfillment\n const where: any = {\n status: { equals: \"published\" },\n productVariants: {\n some: {\n inventoryQuantity: { gt: 0 } // Only products with inventory\n }\n }\n };\n\n if (searchEntry && searchEntry.trim()) {\n where.OR = [\n { title: { contains: searchEntry, mode: \"insensitive\" } },\n { handle: { contains: searchEntry, mode: \"insensitive\" } },\n { productVariants: { some: { sku: { contains: searchEntry, mode: \"insensitive\" } } } }\n ];\n }\n\n // Handle pagination\n const take = 15;\n const skip = after ? parseInt(Buffer.from(after, 'base64').toString()) : 0;\n\n const { products, productsCount } = await openFrontClient.request(gqlQuery, {\n where,\n take,\n skip,\n }) as any;\n\n if (!products || products.length === 0) {\n throw new Error(\"No fulfillment products found from OpenFront\");\n }\n\n // Transform products to Openship channel format\n const transformedProducts = products.flatMap((product: any) => \n product.productVariants\n .filter((variant: any) => variant.inventoryQuantity > 0) // Only variants with inventory\n .map((variant: any) => {\n const firstPrice = variant.prices[0];\n const firstImage = product.productImages[0];\n \n return {\n image: getProductImageUrl(firstImage, platform.domain),\n title: `${product.title} - ${variant.title}`,\n productId: product.id,\n variantId: variant.id,\n price: firstPrice ? (firstPrice.amount / 100).toFixed(2) : \"0.00\", // Convert from cents\n availableForSale: true, // Already filtered above\n inventory: variant.inventoryQuantity,\n inventoryTracked: true,\n productLink: `https://${platform.domain}/products/${product.handle}`,\n cursor: Buffer.from((skip + products.indexOf(product) + 1).toString()).toString('base64'),\n };\n })\n );\n\n const hasNextPage = skip + take < productsCount;\n const endCursor = hasNextPage ? Buffer.from((skip + take).toString()).toString('base64') : null;\n\n return { \n products: transformedProducts, \n pageInfo: {\n hasNextPage,\n endCursor\n }\n };\n}\n\n// Function to get a specific product for fulfillment\nexport async function getProductFunction({\n platform,\n productId,\n variantId,\n}: {\n platform: OpenFrontPlatform;\n productId: string;\n variantId?: string;\n}) {\n console.log(\"OpenFront Channel getProductFunction called with:\", { platform: platform.domain, productId, variantId });\n \n const openFrontClient = await createOpenFrontClient(platform);\n\n const gqlQuery = gql`\n query GetChannelProduct($productId: ID!, $variantId: ID) {\n product(where: { id: $productId }) {\n id\n title\n handle\n productImages {\n image {\n url\n }\n imagePath\n }\n productVariants(where: $variantId ? { id: { equals: $variantId } } : {}) {\n id\n title\n sku\n inventoryQuantity\n prices {\n id\n amount\n currency {\n code\n }\n }\n }\n status\n }\n }\n `;\n\n const { product } = await openFrontClient.request(gqlQuery, {\n productId,\n variantId,\n }) as any;\n\n if (!product || product.status !== \"published\") {\n throw new Error(\"Product not available for fulfillment from OpenFront\");\n }\n\n const variant = variantId \n ? product.productVariants.find((v: any) => v.id === variantId)\n : product.productVariants[0];\n\n if (!variant || variant.inventoryQuantity <= 0) {\n throw new Error(\"Product variant not available for fulfillment from OpenFront\");\n }\n\n const firstPrice = variant.prices[0];\n const firstImage = product.productImages[0];\n\n const transformedProduct = {\n image: getProductImageUrl(firstImage, platform.domain),\n title: `${product.title} - ${variant.title}`,\n productId: product.id,\n variantId: variant.id,\n price: firstPrice ? (firstPrice.amount / 100).toFixed(2) : \"0.00\",\n availableForSale: true,\n inventory: variant.inventoryQuantity,\n inventoryTracked: true,\n productLink: `https://${platform.domain}/products/${product.handle}`,\n };\n\n return { product: transformedProduct };\n}\n\n// Function to create a purchase order (fulfillment order)\nexport async function createPurchaseFunction({\n platform,\n cartItems,\n shipping,\n}: {\n platform: OpenFrontPlatform;\n cartItems: any[];\n shipping: any;\n notes?: string;\n}) {\n console.log(`\uD83D\uDED2 OpenFront Channel: Creating purchase with ${cartItems.length} items`);\n console.log(`\uD83D\uDE9A OpenFront Channel: Ship to: ${shipping?.firstName} ${shipping?.lastName}`);\n\n const openFrontClient = await createOpenFrontClient(platform);\n\n // Generate unique purchase ID\n const purchaseId = `PO-OF-${Date.now()}`;\n const orderNumber = `#${purchaseId}`;\n\n // Calculate total price\n const totalPrice = cartItems.reduce((sum: number, item: any) => {\n return sum + (parseFloat(item.price) * item.quantity);\n }, 0);\n\n // Create fulfillment order in OpenFront\n const createOrderMutation = gql`\n mutation CreateFulfillmentOrder($data: OrderCreateInput!) {\n createOrder(data: $data) {\n id\n orderNumber\n total\n status\n orderLineItems {\n id\n title\n quantity\n unitPrice\n productVariant {\n id\n title\n sku\n product {\n id\n title\n }\n }\n }\n }\n }\n `;\n\n try {\n // Prepare order data\n const orderData = {\n orderNumber,\n customerEmail: shipping?.email || \"fulfillment@openship.org\",\n firstName: shipping?.firstName || \"Fulfillment\",\n lastName: shipping?.lastName || \"Order\",\n address1: shipping?.streetAddress1 || \"\",\n address2: shipping?.streetAddress2 || \"\",\n city: shipping?.city || \"\",\n state: shipping?.state || \"\",\n postalCode: shipping?.zip || \"\",\n countryCode: shipping?.country || \"US\",\n phone: shipping?.phone || \"\",\n total: Math.round(totalPrice * 100), // Convert to cents\n subtotal: Math.round(totalPrice * 100),\n status: \"pending_fulfillment\",\n orderLineItems: {\n create: cartItems.map((item: any) => ({\n title: item.name || `Product ${item.variantId}`,\n quantity: item.quantity,\n unitPrice: Math.round(parseFloat(item.price) * 100), // Convert to cents\n productVariant: { connect: { id: item.variantId } }\n }))\n }\n };\n\n const result = await openFrontClient.request(createOrderMutation, {\n data: orderData,\n }) as any;\n\n const order = result.createOrder;\n\n console.log(`\uD83D\uDCE7 OpenFront Channel: Fulfillment Order Created: ${orderNumber}`);\n console.log(`\uD83D\uDCB0 OpenFront Channel: Total: $${totalPrice.toFixed(2)}`);\n\n // Process line items for response\n const processedLineItems = order.orderLineItems.map((item: any) => ({\n id: item.id,\n title: item.title,\n quantity: item.quantity,\n variantId: item.productVariant.id,\n productId: item.productVariant.product.id\n }));\n\n // Return success response\n return {\n purchaseId: order.id,\n orderNumber: order.orderNumber,\n totalPrice: (order.total / 100).toFixed(2),\n invoiceUrl: `https://${platform.domain}/admin/orders/${order.id}`,\n lineItems: processedLineItems,\n status: \"processing\"\n };\n\n } catch (error) {\n console.error('OpenFront Channel: Purchase creation failed:', error);\n \n // Return error response\n return {\n purchaseId,\n orderNumber,\n totalPrice: totalPrice.toFixed(2),\n invoiceUrl: null,\n lineItems: cartItems.map((item: any) => ({\n id: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n title: item.name || `Product ${item.variantId}`,\n quantity: item.quantity,\n variantId: item.variantId,\n productId: item.productId\n })),\n status: \"error\",\n error: error instanceof Error ? error.message : \"Unknown error\"\n };\n }\n}\n\n// Function to create webhook for channel events\nexport async function createWebhookFunction({\n platform,\n endpoint,\n events,\n}: {\n platform: OpenFrontPlatform;\n endpoint: string;\n events: string[];\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const createWebhookMutation = gql`\n mutation CreateChannelWebhookEndpoint($data: WebhookEndpointCreateInput!) {\n createWebhookEndpoint(data: $data) {\n id\n url\n events\n isActive\n secret\n }\n }\n `;\n\n // Map channel events to OpenFront events\n const eventMap: Record = {\n PURCHASE_CREATED: \"order.created\",\n PURCHASE_SHIPPED: \"fulfillment.shipped\",\n INVENTORY_UPDATED: \"inventory.updated\",\n };\n\n const openFrontEvents = events.map(event => eventMap[event] || event);\n\n const result = await openFrontClient.request(createWebhookMutation, {\n data: {\n url: endpoint,\n events: openFrontEvents,\n isActive: true,\n },\n }) as any;\n\n const webhook = result.createWebhookEndpoint;\n\n return { \n webhooks: [webhook], \n webhookId: webhook.id \n };\n}\n\n// Function to delete webhook\nexport async function deleteWebhookFunction({\n platform,\n webhookId,\n}: {\n platform: OpenFrontPlatform;\n webhookId: string;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const deleteWebhookMutation = gql`\n mutation DeleteChannelWebhookEndpoint($where: WebhookEndpointWhereUniqueInput!) {\n deleteWebhookEndpoint(where: $where) {\n id\n }\n }\n `;\n\n const result = await openFrontClient.request(deleteWebhookMutation, {\n where: { id: webhookId },\n });\n\n return result;\n}\n\n// Function to get webhooks\nexport async function getWebhooksFunction({\n platform,\n}: {\n platform: OpenFrontPlatform;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const query = gql`\n query GetChannelWebhookEndpoints {\n webhookEndpoints(where: { isActive: { equals: true } }) {\n id\n url\n events\n isActive\n createdAt\n }\n }\n `;\n\n const { webhookEndpoints } = await openFrontClient.request(query) as any;\n\n // Map OpenFront events back to channel events\n const eventMap: Record = {\n \"order.created\": \"PURCHASE_CREATED\",\n \"fulfillment.shipped\": \"PURCHASE_SHIPPED\",\n \"inventory.updated\": \"INVENTORY_UPDATED\",\n };\n\n const webhooks = webhookEndpoints.map((webhook: any) => ({\n id: webhook.id,\n callbackUrl: webhook.url,\n topic: webhook.events.map((event: string) => eventMap[event] || event),\n format: \"JSON\",\n createdAt: webhook.createdAt,\n }));\n\n return { webhooks };\n}\n\n// Function to handle purchase tracking updates\nexport async function addTrackingFunction({\n platform,\n purchaseId,\n trackingCompany,\n trackingNumber,\n}: {\n platform: OpenFrontPlatform;\n purchaseId: string;\n trackingCompany: string;\n trackingNumber: string;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n // Update fulfillment order with tracking information\n const updateTrackingMutation = gql`\n mutation UpdateOrderTracking($where: OrderWhereUniqueInput!, $data: OrderUpdateInput!) {\n updateOrder(where: $where, data: $data) {\n id\n orderNumber\n status\n }\n }\n `;\n\n // Create or update fulfillment record\n const createFulfillmentMutation = gql`\n mutation CreateOrderFulfillment($data: FulfillmentCreateInput!) {\n createFulfillment(data: $data) {\n id\n trackingNumber\n trackingCompany\n status\n }\n }\n `;\n\n try {\n // Create fulfillment record\n const fulfillmentResult = await openFrontClient.request(createFulfillmentMutation, {\n data: {\n order: { connect: { id: purchaseId } },\n trackingNumber,\n trackingCompany,\n status: \"shipped\"\n },\n });\n\n // Update order status\n await openFrontClient.request(updateTrackingMutation, {\n where: { id: purchaseId },\n data: { status: \"shipped\" },\n });\n\n console.log(`\uD83D\uDCE6 OpenFront Channel: Tracking added for order ${purchaseId}: ${trackingCompany} ${trackingNumber}`);\n\n return fulfillmentResult;\n } catch (error) {\n console.error('OpenFront Channel: Failed to add tracking:', error);\n throw error;\n }\n}\n\n// Webhook handler for fulfillment updates\nexport async function fulfillmentUpdateWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: OpenFrontPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const signature = headers[\"x-openfront-webhook-signature\"];\n if (!signature) {\n throw new Error(\"Missing webhook signature\");\n }\n\n const fulfillmentData = event.data;\n \n return {\n purchaseId: fulfillmentData.order?.id,\n trackingNumber: fulfillmentData.trackingNumber,\n trackingCompany: fulfillmentData.trackingCompany,\n status: fulfillmentData.status,\n type: \"fulfillment_update\"\n };\n}\n\nexport async function oAuthFunction({\n platform,\n callbackUrl,\n}: {\n platform: OpenFrontPlatform;\n callbackUrl: string;\n}) {\n if (!platform.appKey) {\n throw new Error(\"OpenFront OAuth requires appKey in platform configuration\");\n }\n \n // Generate OpenFront OAuth URL for channel installation\n const scopes = \"read_products,write_products,read_orders,write_orders,read_fulfillments,write_fulfillments,read_webhooks,write_webhooks\";\n const state = (platform as any).state || Math.random().toString(36).substring(7);\n \n // Redirect to apps page with install popup (same as shop integration)\n const openFrontAuthUrl = `${platform.domain}/dashboard/platform/apps?` +\n `install=true&` +\n `client_id=${platform.appKey}&` +\n `scope=${encodeURIComponent(scopes)}&` +\n `redirect_uri=${encodeURIComponent(callbackUrl)}&` +\n `state=${state}&` +\n `response_type=code`;\n \n return { authUrl: openFrontAuthUrl };\n}\n\nexport async function oAuthCallbackFunction({\n platform,\n code,\n shop,\n state,\n appKey,\n appSecret,\n redirectUri,\n}: {\n platform: OpenFrontPlatform;\n code: string;\n shop: string;\n state: string;\n appKey?: string;\n appSecret?: string;\n redirectUri?: string;\n}) {\n // Use platform domain or shop parameter\n const domain = platform.domain || shop;\n const tokenUrl = `${domain}/api/oauth/token`;\n \n // Use passed credentials first (for flexibility), then platform's credentials\n const clientId = appKey || platform.appKey;\n const clientSecret = appSecret || platform.appSecret;\n \n if (!clientId || !clientSecret) {\n throw new Error(\"OpenFront OAuth requires appKey and appSecret in platform configuration or as parameters\");\n }\n \n const formData = new URLSearchParams({\n grant_type: \"authorization_code\",\n client_id: clientId,\n client_secret: clientSecret,\n code,\n redirect_uri: redirectUri || \"\",\n });\n\n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: formData,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error(\"OpenFront OAuth error:\", errorText);\n throw new Error(`Failed to exchange OAuth code for access token: ${response.statusText}`);\n }\n\n const { access_token } = await response.json();\n \n return access_token; // Return just the token, as expected by OpenShip\n}\n\n// Required OAuth scopes for OpenFront channel integration\nconst REQUIRED_SCOPES = \"read_products,write_products,read_orders,write_orders,read_fulfillments,write_fulfillments,read_webhooks,write_webhooks\";\n\nexport function scopes() {\n return REQUIRED_SCOPES;\n}", "import { GraphQLClient, gql } from \"graphql-request\";\n\ninterface ShopifyPlatform {\n domain: string;\n accessToken: string;\n appKey?: string;\n appSecret?: string;\n}\n\ninterface SearchProductsArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface GetProductArgs {\n productId: string;\n variantId?: string;\n}\n\ninterface CreatePurchaseArgs {\n cartItems: Array<{\n variantId: string;\n quantity: number;\n price?: string;\n }>;\n shipping?: {\n firstName: string;\n lastName: string;\n address1: string;\n address2?: string;\n city: string;\n province: string;\n country: string;\n zip: string;\n phone?: string;\n };\n notes?: string;\n}\n\ninterface CreateWebhookArgs {\n endpoint: string;\n events: string[];\n}\n\ninterface DeleteWebhookArgs {\n webhookId: string;\n}\n\ninterface OAuthArgs {\n callbackUrl: string;\n}\n\ninterface OAuthCallbackArgs {\n code: string;\n shop: string;\n state: string;\n}\n\ninterface WebhookEventArgs {\n event: any;\n headers: Record;\n}\n\n// Function to search products for purchasing\nexport async function searchProductsFunction({ \n platform, \n searchEntry, \n after \n}: { \n platform: ShopifyPlatform; \n searchEntry: string; \n after?: string; \n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const gqlQuery = gql`\n query SearchProducts($query: String, $after: String) {\n productVariants(first: 15, query: $query, after: $after) {\n edges {\n node {\n id\n availableForSale\n image {\n originalSrc\n }\n price\n title\n product {\n id\n handle\n title\n images(first: 1) {\n edges {\n node {\n originalSrc\n }\n }\n }\n }\n inventoryQuantity\n inventoryPolicy\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n `;\n\n const result = await shopifyClient.request(gqlQuery, {\n query: searchEntry,\n after,\n }) as any;\n const { productVariants } = result;\n\n if (productVariants.edges.length < 1) {\n throw new Error(\"No products found from Shopify channel\");\n }\n\n const products = productVariants.edges.map(({ node, cursor }: any) => ({\n image:\n node.image?.originalSrc || node.product.images.edges[0]?.node.originalSrc,\n title: `${node.product.title} - ${node.title}`,\n productId: node.product.id.split(\"/\").pop(),\n variantId: node.id.split(\"/\").pop(),\n price: node.price,\n availableForSale: node.availableForSale,\n inventory: node.inventoryQuantity,\n inventoryTracked: node.inventoryPolicy !== \"deny\",\n productLink: `https://${platform.domain}/products/${node.product.handle}`,\n cursor,\n }));\n\n return { \n products, \n pageInfo: productVariants.pageInfo \n };\n}\n\n// Function to get a specific product by variantId and productId\nexport async function getProductFunction({\n platform,\n productId,\n variantId,\n}: {\n platform: ShopifyPlatform;\n productId: string;\n variantId?: string;\n}) {\n console.log(\"CHANNEL getProductFunction called with:\", { platform: platform.domain, productId, variantId });\n \n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const gqlQuery = gql`\n query GetProduct($variantId: ID!) {\n productVariant(id: $variantId) {\n id\n availableForSale\n image {\n originalSrc\n }\n price\n title\n product {\n id\n handle\n title\n images(first: 1) {\n edges {\n node {\n originalSrc\n }\n }\n }\n }\n inventoryQuantity\n inventoryPolicy\n }\n }\n `;\n\n const fullVariantId = `gid://shopify/ProductVariant/${variantId}`;\n console.log(\"CHANNEL querying with variantId:\", fullVariantId);\n \n const variantResult = await shopifyClient.request(gqlQuery, {\n variantId: fullVariantId,\n }) as any;\n const { productVariant } = variantResult;\n\n console.log(\"CHANNEL productVariant result:\", productVariant);\n\n if (!productVariant) {\n throw new Error(\"Product not found from Shopify channel\");\n }\n\n const product = {\n image:\n productVariant.image?.originalSrc ||\n productVariant.product.images.edges[0]?.node.originalSrc,\n title: `${productVariant.product.title} - ${productVariant.title}`,\n productId: productVariant.product.id.split(\"/\").pop(),\n variantId: productVariant.id.split(\"/\").pop(),\n price: productVariant.price,\n availableForSale: productVariant.availableForSale,\n inventory: productVariant.inventoryQuantity,\n inventoryTracked: productVariant.inventoryPolicy !== \"deny\",\n productLink: `https://${platform.domain}/products/${productVariant.product.handle}`,\n };\n\n return { product };\n}\n\nexport async function createPurchaseFunction({\n platform,\n cartItems,\n shipping,\n notes,\n}: {\n platform: ShopifyPlatform;\n cartItems: CreatePurchaseArgs['cartItems'];\n shipping?: CreatePurchaseArgs['shipping'];\n notes?: string;\n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const mutation = gql`\n mutation CreateDraftOrder($input: DraftOrderInput!) {\n draftOrderCreate(input: $input) {\n draftOrder {\n id\n name\n invoiceUrl\n totalPrice\n lineItems(first: 50) {\n edges {\n node {\n id\n title\n quantity\n originalUnitPrice\n variant {\n id\n title\n product {\n id\n title\n }\n }\n }\n }\n }\n shippingAddress {\n firstName\n lastName\n address1\n address2\n city\n province\n country\n zip\n phone\n }\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const lineItems = cartItems.map(item => ({\n variantId: `gid://shopify/ProductVariant/${item.variantId}`,\n quantity: item.quantity,\n originalUnitPrice: item.price,\n }));\n\n const input: any = {\n lineItems,\n note: notes,\n };\n\n if (shipping) {\n input.shippingAddress = {\n firstName: shipping.firstName,\n lastName: shipping.lastName,\n address1: shipping.address1,\n address2: shipping.address2,\n city: shipping.city,\n province: shipping.province,\n country: shipping.country,\n zip: shipping.zip,\n phone: shipping.phone,\n };\n }\n\n const result = await shopifyClient.request(mutation, { input }) as any;\n\n if (result.draftOrderCreate.userErrors.length > 0) {\n throw new Error(`Failed to create purchase: ${result.draftOrderCreate.userErrors.map((e: any) => e.message).join(', ')}`);\n }\n\n const draftOrder = result.draftOrderCreate.draftOrder;\n\n // Complete the draft order to create an actual order\n const completeMutation = gql`\n mutation CompleteDraftOrder($id: ID!) {\n draftOrderComplete(id: $id) {\n draftOrder {\n id\n order {\n id\n name\n totalPrice\n lineItems(first: 50) {\n edges {\n node {\n id\n title\n quantity\n variant {\n id\n }\n }\n }\n }\n }\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const completeResult = await shopifyClient.request(completeMutation, {\n id: draftOrder.id,\n }) as any;\n\n if (completeResult.draftOrderComplete.userErrors.length > 0) {\n throw new Error(`Failed to complete purchase: ${completeResult.draftOrderComplete.userErrors.map((e: any) => e.message).join(', ')}`);\n }\n\n const order = completeResult.draftOrderComplete.draftOrder.order;\n\n return {\n purchaseId: order.id.split(\"/\").pop(),\n orderNumber: order.name,\n totalPrice: order.totalPrice,\n invoiceUrl: draftOrder.invoiceUrl,\n lineItems: order.lineItems.edges.map(({ node }: any) => ({\n id: node.id.split(\"/\").pop(),\n title: node.title,\n quantity: node.quantity,\n variantId: node.variant.id.split(\"/\").pop(),\n })),\n status: \"pending\",\n };\n}\n\nexport async function createWebhookFunction({\n platform,\n endpoint,\n events,\n}: {\n platform: ShopifyPlatform;\n endpoint: string;\n events: string[];\n}) {\n const mapTopic: Record = {\n ORDER_CREATED: \"ORDERS_CREATE\",\n ORDER_CANCELLED: \"ORDERS_CANCELLED\",\n ORDER_CHARGEBACKED: \"DISPUTES_CREATE\",\n TRACKING_CREATED: \"FULFILLMENTS_CREATE\",\n };\n\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const webhooks = [];\n\n for (const event of events) {\n const shopifyTopic = mapTopic[event] || event;\n const mutation = gql`\n mutation webhookSubscriptionCreate($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) {\n webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) {\n webhookSubscription {\n id\n endpoint {\n __typename\n ... on WebhookHttpEndpoint {\n callbackUrl\n }\n }\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const result = await shopifyClient.request(mutation, {\n topic: shopifyTopic.toUpperCase(),\n webhookSubscription: {\n callbackUrl: endpoint,\n format: \"JSON\",\n },\n }) as any;\n\n webhooks.push(result.webhookSubscriptionCreate.webhookSubscription);\n }\n\n return { webhooks };\n}\n\nexport async function deleteWebhookFunction({\n platform,\n webhookId,\n}: {\n platform: ShopifyPlatform;\n webhookId: string;\n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const mutation = gql`\n mutation DeleteWebhook($id: ID!) {\n webhookSubscriptionDelete(id: $id) {\n deletedWebhookSubscriptionId\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const result = await shopifyClient.request(mutation, {\n id: `gid://shopify/WebhookSubscription/${webhookId}`,\n }) as any;\n\n return (result as any).webhookSubscriptionDelete;\n}\n\nexport async function getWebhooksFunction({\n platform,\n}: {\n platform: ShopifyPlatform;\n}) {\n const mapTopic = {\n ORDERS_CREATE: \"ORDER_CREATED\",\n ORDERS_CANCELLED: \"ORDER_CANCELLED\",\n DISPUTES_CREATE: \"ORDER_CHARGEBACKED\",\n FULFILLMENTS_CREATE: \"TRACKING_CREATED\",\n };\n\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const query = gql`\n query GetWebhooks {\n webhookSubscriptions(first: 50) {\n edges {\n node {\n id\n topic\n format\n createdAt\n endpoint {\n __typename\n ... on WebhookHttpEndpoint {\n callbackUrl\n }\n }\n }\n }\n }\n }\n `;\n\n const webhooksResult = await shopifyClient.request(query) as any;\n const { webhookSubscriptions } = webhooksResult;\n\n const webhooks = webhookSubscriptions.edges.map(({ node }: any) => ({\n id: node.id.split(\"/\").pop(),\n callbackUrl: node.endpoint.callbackUrl,\n topic: (mapTopic as any)[node.topic] || node.topic,\n format: node.format,\n createdAt: node.createdAt,\n }));\n\n return { webhooks };\n}\n\nexport async function oAuthFunction({\n platform,\n callbackUrl,\n}: {\n platform: ShopifyPlatform;\n callbackUrl: string;\n}) {\n // Use platform's appKey if available, otherwise fall back to env variable for backward compatibility\n const clientId = platform.appKey || process.env.SHOPIFY_APP_KEY;\n \n if (!clientId) {\n throw new Error(\"Shopify OAuth requires appKey in platform config or SHOPIFY_APP_KEY environment variable\");\n }\n \n const scopes = \"read_products,write_products,read_orders,write_orders,read_inventory,write_inventory\";\n const shopifyAuthUrl = `https://${platform.domain}/admin/oauth/authorize?client_id=${clientId}&scope=${scopes}&redirect_uri=${callbackUrl}&state=${Math.random().toString(36).substring(7)}`;\n \n return { authUrl: shopifyAuthUrl };\n}\n\nexport async function oAuthCallbackFunction({\n platform,\n code,\n shop,\n state,\n}: {\n platform: ShopifyPlatform;\n code: string;\n shop: string;\n state: string;\n}) {\n // Use platform credentials if available, otherwise fall back to env variables for backward compatibility\n const clientId = platform.appKey || process.env.SHOPIFY_APP_KEY;\n const clientSecret = platform.appSecret || process.env.SHOPIFY_APP_SECRET;\n \n if (!clientId || !clientSecret) {\n throw new Error(\"Shopify OAuth requires appKey and appSecret in platform config or environment variables\");\n }\n \n const tokenUrl = `https://${shop}/admin/oauth/access_token`;\n \n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n client_id: clientId,\n client_secret: clientSecret,\n code,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\"Failed to exchange OAuth code for access token\");\n }\n\n const { access_token } = await response.json();\n \n return { \n accessToken: access_token,\n domain: shop,\n };\n}\n\nexport async function createTrackingWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: ShopifyPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const hmac = headers[\"x-shopify-hmac-sha256\"];\n if (!hmac) {\n throw new Error(\"Missing webhook HMAC\");\n }\n\n // Process the fulfillment data\n const fulfillment = {\n id: event.id,\n orderId: event.order_id,\n status: event.status,\n trackingCompany: event.tracking_company,\n trackingNumber: event.tracking_number,\n trackingUrl: event.tracking_url,\n purchaseId: event.order_id?.toString(), // Use order ID as purchaseId\n lineItems: event.line_items.map((item: any) => ({\n id: item.id,\n title: item.title,\n quantity: item.quantity,\n variantId: item.variant_id,\n productId: item.product_id,\n })),\n createdAt: event.created_at,\n updatedAt: event.updated_at,\n };\n\n return { fulfillment, type: \"fulfillment_created\" };\n}\n\nexport async function cancelPurchaseWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: ShopifyPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const hmac = headers[\"x-shopify-hmac-sha256\"];\n if (!hmac) {\n throw new Error(\"Missing webhook HMAC\");\n }\n\n const order = {\n id: event.id,\n name: event.name,\n cancelReason: event.cancel_reason,\n cancelledAt: event.cancelled_at,\n refund: event.refunds?.[0] || null,\n };\n\n return { order, type: \"purchase_cancelled\" };\n}\n\n// Required OAuth scopes for Shopify channel integration\nconst REQUIRED_SCOPES = \"read_products,write_products,read_orders,write_orders,read_inventory,write_inventory\";\n\nexport function scopes() {\n return REQUIRED_SCOPES;\n}", "export async function executeChannelAdapterFunction({ platform, functionName, args }: { platform: any; functionName: string; args: any }) {\n const functionPath = platform[functionName];\n\n if (functionPath.startsWith(\"http\")) {\n const response = await fetch(functionPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform, ...args }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP request failed: ${response.statusText}`);\n }\n return response.json();\n }\n\n const adapter = await import(\n `../${functionPath}.ts`\n );\n\n const fn = adapter[functionName];\n if (!fn) {\n throw new Error(\n `Function ${functionName} not found in adapter ${functionPath}`\n );\n }\n\n try {\n return await fn({ platform, ...args });\n } catch (error) {\n throw new Error(\n `Error executing ${functionName} for platform ${functionPath}: ${(error as Error).message}`\n );\n }\n}\n\n// Helper functions for common channel operations\nexport async function searchChannelProducts({ platform, searchEntry, after }: { platform: any; searchEntry: string; after?: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"searchProductsFunction\",\n args: { searchEntry, after },\n });\n}\n\nexport async function getChannelProduct({ platform, productId }: { platform: any; productId: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"getProductFunction\",\n args: { productId },\n });\n}\n\nexport async function createChannelPurchase({ platform, cartItems, shipping, notes }: { platform: any; cartItems: any; shipping: any; notes?: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"createPurchaseFunction\",\n args: { cartItems, shipping, notes },\n });\n}\n\nexport async function createChannelWebhook({ platform, endpoint, events }: { platform: any; endpoint: string; events: string[] }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"createWebhookFunction\",\n args: { endpoint, events },\n });\n}\n\nexport async function deleteChannelWebhook({ platform, webhookId }: { platform: any; webhookId: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"deleteWebhookFunction\",\n args: { webhookId },\n });\n}\n\nexport async function getChannelWebhooks({ platform }: { platform: any }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"getWebhooksFunction\",\n args: {},\n });\n}\n\nexport async function handleChannelOAuth({ platform, callbackUrl }: { platform: any; callbackUrl: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"oAuthFunction\",\n args: { callbackUrl },\n });\n}\n\nexport async function handleChannelOAuthCallback({ platform, code, shop, state, appKey, appSecret, redirectUri }: { platform: any; code?: string; shop?: string; state?: string; appKey?: string; appSecret?: string; redirectUri?: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"oAuthCallbackFunction\",\n args: { code, shop, state, appKey, appSecret, redirectUri },\n });\n}\n\nexport async function handleChannelTrackingWebhook({ platform, event, headers }: { platform: any; event: any; headers: any }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"createTrackingWebhookHandler\",\n args: { event, headers },\n });\n}\n\nexport async function handleChannelCancelWebhook({ platform, event, headers }: { platform: any; event: any; headers: any }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"cancelPurchaseWebhookHandler\",\n args: { event, headers },\n });\n}", "import { GraphQLClient, gql } from \"graphql-request\";\nimport { getBaseUrl } from '@/features/dashboard/lib/getBaseUrl';\n\ninterface OpenFrontPlatform {\n domain: string;\n accessToken: string;\n refreshToken?: string;\n tokenExpiresAt?: Date | string;\n appKey?: string;\n appSecret?: string;\n}\n\ninterface SearchProductsArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface GetProductArgs {\n productId: string;\n variantId?: string;\n}\n\ninterface SearchOrdersArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface UpdateProductArgs {\n productId: string;\n variantId: string;\n inventory?: number;\n price?: string;\n}\n\ninterface CreateWebhookArgs {\n endpoint: string;\n events: string[];\n}\n\ninterface DeleteWebhookArgs {\n webhookId: string;\n}\n\ninterface OAuthArgs {\n callbackUrl: string;\n}\n\ninterface OAuthCallbackArgs {\n code: string;\n shop: string;\n state: string;\n}\n\ninterface WebhookEventArgs {\n event: any;\n headers: Record;\n}\n\n// Helper function to get fresh access token with proper OAuth 2.0 flow\nconst getFreshAccessToken = async (platform: OpenFrontPlatform) => {\n // Check if we have local access token expiry information\n if (platform.tokenExpiresAt && platform.refreshToken) {\n const expiresAt = typeof platform.tokenExpiresAt === 'string' \n ? new Date(platform.tokenExpiresAt) \n : platform.tokenExpiresAt;\n \n // If access token hasn't expired yet, use it\n if (expiresAt > new Date()) {\n return platform.accessToken;\n }\n \n \n // Use refresh token to get new access token\n const tokenUrl = `${platform.domain}/api/oauth/token`;\n \n const formData = new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: platform.refreshToken,\n });\n\n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: formData,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('Token refresh failed:', errorText);\n throw new Error(`Failed to refresh access token: ${response.statusText} - ${errorText}`);\n }\n\n const { access_token } = await response.json();\n \n // TODO: Update stored access token and expiry in database\n // This would require updating the shop/channel record with new tokens\n \n return access_token;\n }\n \n \n // If no refresh capability, just use the access token as-is\n return platform.accessToken;\n};\n\n// Helper function to create OpenFront GraphQL client with fresh token\nconst createOpenFrontClient = async (platform: OpenFrontPlatform) => {\n const freshAccessToken = await getFreshAccessToken(platform);\n \n return new GraphQLClient(\n `${platform.domain}/api/graphql`,\n {\n headers: {\n \"Authorization\": `Bearer ${freshAccessToken}`,\n \"Content-Type\": \"application/json\",\n },\n }\n );\n};\n\n// Helper function to get product image URL\n// imagePath is a relative path (e.g., \"/images/product.jpg\") that needs domain prepended\n// image.url is an absolute S3 URL that can be used directly\nconst getProductImageUrl = (productImage: any, domain: string): string | null => {\n if (productImage?.imagePath) {\n return `${domain}${productImage.imagePath}`;\n }\n return productImage?.image?.url || null;\n};\n\n// Function to search products\nexport async function searchProductsFunction({ \n platform, \n searchEntry, \n after \n}: { \n platform: OpenFrontPlatform; \n searchEntry: string; \n after?: string; \n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const gqlQuery = gql`\n query SearchProducts($where: ProductWhereInput, $take: Int, $skip: Int) {\n products(where: $where, take: $take, skip: $skip, orderBy: { createdAt: desc }) {\n id\n title\n handle\n description {\n document\n }\n productImages {\n image {\n url\n }\n imagePath\n }\n productVariants {\n id\n title\n sku\n inventoryQuantity\n prices {\n id\n amount\n currency {\n code\n }\n region {\n countries {\n iso2\n }\n }\n }\n }\n productCollections {\n id\n title\n }\n metadata\n status\n createdAt\n }\n productsCount(where: $where)\n }\n `;\n\n // Build search filter\n const where: any = {\n status: { equals: \"published\" }\n };\n\n if (searchEntry && searchEntry.trim()) {\n where.OR = [\n { title: { contains: searchEntry, mode: \"insensitive\" } },\n { handle: { contains: searchEntry, mode: \"insensitive\" } },\n { productVariants: { some: { sku: { contains: searchEntry, mode: \"insensitive\" } } } }\n ];\n }\n\n // Handle pagination\n const take = 15;\n const skip = after ? parseInt(Buffer.from(after, 'base64').toString()) : 0;\n\n const { products, productsCount } = await openFrontClient.request(gqlQuery, {\n where,\n take,\n skip,\n }) as any;\n\n if (!products || products.length === 0) {\n throw new Error(\"No products found from OpenFront\");\n }\n\n // Transform products to Openship format\n const transformedProducts = products.flatMap((product: any) => \n product.productVariants.map((variant: any) => {\n const firstPrice = variant.prices[0];\n const firstImage = product.productImages[0];\n \n return {\n image: getProductImageUrl(firstImage, platform.domain),\n title: `${product.title} - ${variant.title}`,\n productId: product.id,\n variantId: variant.id,\n price: firstPrice ? (firstPrice.amount / 100).toFixed(2) : \"0.00\", // Convert from cents\n availableForSale: product.status === \"published\" && variant.inventoryQuantity > 0,\n inventory: variant.inventoryQuantity || 0,\n inventoryTracked: true,\n productLink: `https://${platform.domain}/products/${product.handle}`,\n cursor: Buffer.from((skip + products.indexOf(product) + 1).toString()).toString('base64'),\n };\n })\n );\n\n const hasNextPage = skip + take < productsCount;\n const endCursor = hasNextPage ? Buffer.from((skip + take).toString()).toString('base64') : null;\n\n return { \n products: transformedProducts, \n pageInfo: {\n hasNextPage,\n endCursor\n }\n };\n}\n\n// Function to get a specific product by variantId and productId\nexport async function getProductFunction({\n platform,\n productId,\n variantId,\n}: {\n platform: OpenFrontPlatform;\n productId: string;\n variantId?: string;\n}) {\n console.log(\"OpenFront getProductFunction called with:\", { platform: platform.domain, productId, variantId });\n \n const openFrontClient = await createOpenFrontClient(platform);\n\n // Build the query conditionally based on whether variantId is provided\n const gqlQuery = variantId ? gql`\n query GetProduct($productId: ID!, $variantId: ID!) {\n product(where: { id: $productId }) {\n id\n title\n handle\n description {\n document\n }\n productImages {\n image {\n url\n }\n imagePath\n }\n productVariants(where: { id: { equals: $variantId } }) {\n id\n title\n sku\n inventoryQuantity\n prices {\n id\n amount\n currency {\n code\n }\n }\n }\n status\n }\n }\n ` : gql`\n query GetProduct($productId: ID!) {\n product(where: { id: $productId }) {\n id\n title\n handle\n description {\n document\n }\n productImages {\n image {\n url\n }\n imagePath\n }\n productVariants {\n id\n title\n sku\n inventoryQuantity\n prices {\n id\n amount\n currency {\n code\n }\n }\n }\n status\n }\n }\n `;\n\n const variables: any = { productId };\n if (variantId) {\n variables.variantId = variantId;\n }\n\n const { product } = await openFrontClient.request(gqlQuery, variables) as any;\n\n if (!product) {\n throw new Error(\"Product not found from OpenFront\");\n }\n\n const variant = variantId \n ? product.productVariants.find((v: any) => v.id === variantId)\n : product.productVariants[0];\n\n if (!variant) {\n throw new Error(\"Product variant not found from OpenFront\");\n }\n\n const firstPrice = variant.prices[0];\n const firstImage = product.productImages[0];\n\n const transformedProduct = {\n image: getProductImageUrl(firstImage, platform.domain),\n title: `${product.title} - ${variant.title}`,\n productId: product.id,\n variantId: variant.id,\n price: firstPrice ? (firstPrice.amount / 100).toFixed(2) : \"0.00\",\n availableForSale: product.status === \"published\" && variant.inventoryQuantity > 0,\n inventory: variant.inventoryQuantity || 0,\n inventoryTracked: true,\n productLink: `https://${platform.domain}/products/${product.handle}`,\n };\n\n return { product: transformedProduct };\n}\n\nexport async function searchOrdersFunction({\n platform,\n searchEntry,\n after,\n}: {\n platform: OpenFrontPlatform;\n searchEntry: string;\n after?: string;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const gqlQuery = gql`\n query SearchOrders($where: OrderWhereInput, $take: Int, $skip: Int) {\n orders(where: $where, take: $take, skip: $skip, orderBy: { createdAt: desc }) {\n id\n displayId\n email\n status\n total\n rawTotal\n currency {\n code\n }\n shippingAddress {\n firstName\n lastName\n address1\n address2\n city\n province\n postalCode\n phone\n country {\n iso2\n }\n }\n lineItems {\n id\n title\n quantity\n sku\n variantTitle\n thumbnail\n formattedUnitPrice\n formattedTotal\n moneyAmount {\n amount\n originalAmount\n }\n productVariant {\n id\n title\n sku\n product {\n id\n title\n handle\n thumbnail\n }\n }\n productData\n variantData\n }\n createdAt\n updatedAt\n }\n ordersCount(where: $where)\n }\n `;\n\n // Build search filter\n const where: any = {};\n\n if (searchEntry && searchEntry.trim()) {\n where.OR = [\n { displayId: { contains: searchEntry, mode: \"insensitive\" } },\n { email: { contains: searchEntry, mode: \"insensitive\" } },\n { shippingAddress: { \n is: {\n OR: [\n { firstName: { contains: searchEntry, mode: \"insensitive\" } },\n { lastName: { contains: searchEntry, mode: \"insensitive\" } }\n ]\n }\n }}\n ];\n }\n\n // Handle pagination\n const take = 15;\n const skip = after ? parseInt(Buffer.from(after, 'base64').toString()) : 0;\n\n const { orders, ordersCount } = await openFrontClient.request(gqlQuery, {\n where,\n take,\n skip,\n }) as any;\n\n // Transform orders to Openship format\n const transformedOrders = orders.map((order: any) => {\n const shippingAddress = order.shippingAddress || {};\n \n return {\n orderId: order.id,\n orderName: `#${order.displayId}`,\n link: `${platform.domain}/admin/orders/${order.id}`,\n date: new Date(order.createdAt).toLocaleDateString(),\n firstName: shippingAddress.firstName || \"\",\n lastName: shippingAddress.lastName || \"\",\n streetAddress1: shippingAddress.address1 || \"\",\n streetAddress2: shippingAddress.address2 || \"\",\n city: shippingAddress.city || \"\",\n state: shippingAddress.province || \"\",\n zip: shippingAddress.postalCode || \"\",\n country: shippingAddress.country?.iso2 || \"\",\n email: order.email || \"\",\n fulfillmentStatus: order.status,\n financialStatus: order.status,\n totalPrice: order.rawTotal ? (order.rawTotal / 100).toFixed(2) : \"0.00\",\n currency: order.currency?.code || \"USD\",\n lineItems: (order.lineItems || []).map((lineItem: any) => ({\n lineItemId: lineItem.id,\n name: lineItem.title,\n quantity: lineItem.quantity,\n image: getProductImageUrl({ imagePath: lineItem.thumbnail, image: { url: lineItem.productVariant?.product?.thumbnail } }, platform.domain) || \"\",\n price: lineItem.moneyAmount ? (lineItem.moneyAmount.amount / 100).toFixed(2) : \"0.00\",\n variantId: lineItem.productVariant?.id || \"\",\n productId: lineItem.productVariant?.product?.id || \"\",\n sku: lineItem.sku || lineItem.productVariant?.sku || \"\",\n })),\n cartItems: [],\n fulfillments: [],\n note: \"\",\n cursor: Buffer.from((skip + orders.indexOf(order) + 1).toString()).toString('base64'),\n };\n });\n\n const hasNextPage = skip + take < ordersCount;\n const endCursor = hasNextPage ? Buffer.from((skip + take).toString()).toString('base64') : null;\n\n return { \n orders: transformedOrders, \n pageInfo: {\n hasNextPage,\n endCursor\n }\n };\n}\n\nexport async function updateProductFunction({\n platform,\n productId,\n variantId,\n inventory,\n price,\n}: {\n platform: OpenFrontPlatform;\n productId: string;\n variantId: string;\n inventory?: number;\n price?: string;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const mutations = [];\n\n if (inventory !== undefined) {\n const updateInventoryMutation = gql`\n mutation UpdateProductVariantInventory($where: ProductVariantWhereUniqueInput!, $data: ProductVariantUpdateInput!) {\n updateProductVariant(where: $where, data: $data) {\n id\n inventoryQuantity\n }\n }\n `;\n\n mutations.push(\n openFrontClient.request(updateInventoryMutation, {\n where: { id: variantId },\n data: { inventoryQuantity: inventory },\n })\n );\n }\n\n if (price !== undefined) {\n // Note: Price updates in OpenFront might require updating the Price model separately\n // This is a simplified approach - you might need to adjust based on your schema\n console.log(`Price update requested for variant ${variantId}: ${price}`);\n // Actual price update would depend on how prices are structured in OpenFront\n }\n\n const results = await Promise.all(mutations);\n return { success: true, results };\n}\n\nexport async function createWebhookFunction({\n platform,\n endpoint,\n events,\n}: {\n platform: OpenFrontPlatform;\n endpoint: string;\n events: string[];\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const createWebhookMutation = gql`\n mutation CreateWebhookEndpoint($data: WebhookEndpointCreateInput!) {\n createWebhookEndpoint(data: $data) {\n id\n url\n events\n isActive\n secret\n }\n }\n `;\n\n // Map Openship events to OpenFront events\n const eventMap: Record = {\n ORDER_CREATED: \"order.created\",\n ORDER_CANCELLED: \"order.cancelled\",\n TRACKING_CREATED: \"fulfillment.created\",\n };\n\n const openFrontEvents = events.map(event => eventMap[event] || event);\n\n const result = await openFrontClient.request(createWebhookMutation, {\n data: {\n url: endpoint,\n events: openFrontEvents,\n isActive: true,\n },\n }) as any;\n\n const webhook = result.createWebhookEndpoint;\n\n return { \n webhooks: [webhook], \n webhookId: webhook.id \n };\n}\n\nexport async function deleteWebhookFunction({\n platform,\n webhookId,\n}: {\n platform: OpenFrontPlatform;\n webhookId: string;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const deleteWebhookMutation = gql`\n mutation DeleteWebhookEndpoint($where: WebhookEndpointWhereUniqueInput!) {\n deleteWebhookEndpoint(where: $where) {\n id\n }\n }\n `;\n\n const result = await openFrontClient.request(deleteWebhookMutation, {\n where: { id: webhookId },\n });\n\n return result;\n}\n\nexport async function getWebhooksFunction({\n platform,\n}: {\n platform: OpenFrontPlatform;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const query = gql`\n query GetWebhookEndpoints {\n webhookEndpoints(where: { isActive: { equals: true } }) {\n id\n url\n events\n isActive\n createdAt\n }\n }\n `;\n\n const { webhookEndpoints } = await openFrontClient.request(query) as any;\n\n const baseUrl = await getBaseUrl();\n \n // Map OpenFront events back to Openship events\n const eventMap: Record = {\n \"order.created\": \"ORDER_CREATED\",\n \"order.cancelled\": \"ORDER_CANCELLED\", \n \"fulfillment.created\": \"TRACKING_CREATED\",\n };\n\n const webhooks = webhookEndpoints.map((webhook: any) => ({\n id: webhook.id,\n callbackUrl: webhook.url.replace(baseUrl, \"\"),\n topic: webhook.events.map((event: string) => eventMap[event] || event),\n format: \"JSON\",\n createdAt: webhook.createdAt,\n }));\n\n return { webhooks };\n}\n\nexport async function oAuthFunction({\n platform,\n callbackUrl,\n}: {\n platform: OpenFrontPlatform;\n callbackUrl: string;\n}) {\n \n if (!platform.appKey) {\n throw new Error(\"OpenFront OAuth requires appKey in platform configuration\");\n }\n \n // Generate OpenFront OAuth URL\n const scopes = \"read_products,write_products,read_orders,write_orders,read_customers,write_customers,read_webhooks,write_webhooks\";\n const state = (platform as any).state || Math.random().toString(36).substring(7);\n \n // Redirect to apps page with install popup\n const openFrontAuthUrl = `${platform.domain}/dashboard/platform/apps?` +\n `install=true&` +\n `client_id=${platform.appKey}&` +\n `scope=${encodeURIComponent(scopes)}&` +\n `redirect_uri=${encodeURIComponent(callbackUrl)}&` +\n `state=${state}&` +\n `response_type=code`;\n \n \n return { authUrl: openFrontAuthUrl };\n}\n\nexport async function oAuthCallbackFunction({\n platform,\n code,\n shop,\n state,\n appKey,\n appSecret,\n redirectUri,\n}: {\n platform: OpenFrontPlatform;\n code: string;\n shop: string;\n state: string;\n appKey?: string;\n appSecret?: string;\n redirectUri?: string;\n}) {\n // Use platform domain or shop parameter\n const domain = platform.domain || shop;\n const tokenUrl = `${domain}/api/oauth/token`;\n \n // Use passed credentials first (for flexibility), then platform's credentials\n const clientId = appKey || platform.appKey;\n const clientSecret = appSecret || platform.appSecret;\n \n \n if (!clientId || !clientSecret) {\n throw new Error(\"OpenFront OAuth requires appKey and appSecret in platform configuration or as parameters\");\n }\n \n const formData = new URLSearchParams({\n grant_type: \"authorization_code\",\n client_id: clientId,\n client_secret: clientSecret,\n code,\n redirect_uri: redirectUri || \"\",\n });\n\n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: formData,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error(\"OpenFront OAuth error:\", errorText);\n throw new Error(`Failed to exchange OAuth code for access token: ${response.statusText}`);\n }\n\n const { access_token, refresh_token, expires_in } = await response.json();\n \n // Return OAuth token data for proper storage\n return {\n access_token,\n refresh_token,\n expires_in,\n expires_at: new Date(Date.now() + (expires_in * 1000))\n };\n}\n\nexport async function createOrderWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: OpenFrontPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity using OpenFront's signature\n const signature = headers[\"x-openfront-webhook-signature\"];\n if (!signature) {\n throw new Error(\"Missing webhook signature\");\n }\n\n // Transform OpenFront order to Openship format\n const lineItemsOutput = event.data?.orderLineItems?.map((item: any) => ({\n name: item.title,\n image: getProductImageUrl(item.productVariant?.product?.productImages?.[0], platform.domain),\n price: item.unitPrice ? (item.unitPrice / 100) : 0, // Convert from cents, handle null/undefined\n quantity: item.quantity || 0,\n productId: item.productVariant?.product?.id,\n variantId: item.productVariant?.id,\n sku: item.productVariant?.sku || \"\",\n lineItemId: item.id,\n })) || [];\n\n // Return Keystone-ready order data\n const orderData = event.data;\n return {\n orderId: orderData.id,\n orderName: orderData.orderNumber,\n email: orderData.customerEmail,\n firstName: orderData.firstName,\n lastName: orderData.lastName,\n streetAddress1: orderData.address1,\n streetAddress2: orderData.address2,\n city: orderData.city,\n state: orderData.state,\n zip: orderData.postalCode,\n country: orderData.countryCode,\n phone: orderData.phone,\n currency: orderData.currency?.code || \"USD\",\n totalPrice: orderData.total ? (orderData.total / 100) : 0, // Convert from cents, handle null/undefined\n subTotalPrice: (orderData.subtotal || orderData.total) ? ((orderData.subtotal || orderData.total) / 100) : 0,\n totalDiscounts: orderData.totalDiscounts ? (orderData.totalDiscounts / 100) : 0,\n totalTax: orderData.totalTax ? (orderData.totalTax / 100) : 0,\n status: \"INPROCESS\",\n linkOrder: true,\n matchOrder: true,\n processOrder: true,\n lineItems: { create: lineItemsOutput },\n };\n}\n\nexport async function cancelOrderWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: OpenFrontPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const signature = headers[\"x-openfront-webhook-signature\"];\n if (!signature) {\n throw new Error(\"Missing webhook signature\");\n }\n\n const orderData = event.data;\n const order = {\n id: orderData.id,\n name: orderData.orderNumber,\n cancelReason: orderData.cancellationReason || \"merchant_cancelled\",\n cancelledAt: new Date().toISOString(),\n };\n\n return { order, type: \"order_cancelled\" };\n}\n\n// Required OAuth scopes for OpenFront shop integration\nconst REQUIRED_SCOPES = \"read_products,write_products,read_orders,write_orders,read_customers,write_customers,read_webhooks,write_webhooks\";\n\nexport function scopes() {\n return REQUIRED_SCOPES;\n}\n\nexport async function addTrackingFunction({\n order,\n trackingCompany,\n trackingNumber,\n}: {\n order: any;\n trackingCompany: string;\n trackingNumber: string;\n}) {\n const openFrontClient = await createOpenFrontClient({\n domain: order.shop.domain,\n accessToken: order.shop.accessToken,\n });\n\n // Create fulfillment record in OpenFront\n const createFulfillmentMutation = gql`\n mutation CreateFulfillment($data: FulfillmentCreateInput!) {\n createFulfillment(data: $data) {\n id\n trackingNumber\n trackingCompany\n }\n }\n `;\n\n const fulfillmentData = {\n order: { connect: { id: order.orderId } },\n trackingNumber,\n trackingCompany,\n status: \"shipped\",\n };\n\n const result = await openFrontClient.request(createFulfillmentMutation, {\n data: fulfillmentData,\n });\n\n return result;\n}", "import { GraphQLClient, gql } from \"graphql-request\";\nimport { getBaseUrl } from '@/features/dashboard/lib/getBaseUrl';\n\ninterface ShopifyPlatform {\n domain: string;\n accessToken: string;\n appKey?: string;\n appSecret?: string;\n}\n\ninterface SearchProductsArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface GetProductArgs {\n productId: string;\n variantId?: string;\n}\n\ninterface SearchOrdersArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface UpdateProductArgs {\n productId: string;\n variantId: string;\n inventory?: number;\n price?: string;\n}\n\ninterface CreateWebhookArgs {\n endpoint: string;\n events: string[];\n}\n\ninterface DeleteWebhookArgs {\n webhookId: string;\n}\n\ninterface OAuthArgs {\n callbackUrl: string;\n}\n\ninterface OAuthCallbackArgs {\n code: string;\n shop: string;\n state: string;\n}\n\ninterface WebhookEventArgs {\n event: any;\n headers: Record;\n}\n\n// Function to search products\nexport async function searchProductsFunction({ \n platform, \n searchEntry, \n after \n}: { \n platform: ShopifyPlatform; \n searchEntry: string; \n after?: string; \n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const gqlQuery = gql`\n query SearchProducts($query: String, $after: String) {\n productVariants(first: 15, query: $query, after: $after) {\n edges {\n node {\n id\n availableForSale\n image {\n originalSrc\n }\n price\n title\n product {\n id\n handle\n title\n images(first: 1) {\n edges {\n node {\n originalSrc\n }\n }\n }\n }\n inventoryQuantity\n inventoryPolicy\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n `;\n\n const { productVariants } = await shopifyClient.request(gqlQuery, {\n query: searchEntry,\n after,\n }) as any;\n\n if (productVariants.edges.length < 1) {\n throw new Error(\"No products found from Shopify\");\n }\n\n const products = productVariants.edges.map(({ node, cursor }: any) => ({\n image:\n node.image?.originalSrc || node.product.images.edges[0]?.node.originalSrc,\n title: `${node.product.title} - ${node.title}`,\n productId: node.product.id.split(\"/\").pop(),\n variantId: node.id.split(\"/\").pop(),\n price: node.price,\n availableForSale: node.availableForSale,\n inventory: node.inventoryQuantity,\n inventoryTracked: node.inventoryPolicy !== \"deny\",\n productLink: `https://${platform.domain}/products/${node.product.handle}`,\n cursor,\n }));\n\n return { \n products, \n pageInfo: productVariants.pageInfo \n };\n}\n\n// Function to get a specific product by variantId and productId\nexport async function getProductFunction({\n platform,\n productId,\n variantId,\n}: {\n platform: ShopifyPlatform;\n productId: string;\n variantId?: string;\n}) {\n console.log(\"SHOP getProductFunction called with:\", { platform: platform.domain, productId, variantId });\n \n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const gqlQuery = gql`\n query GetProduct($variantId: ID!) {\n productVariant(id: $variantId) {\n id\n availableForSale\n image {\n originalSrc\n }\n price\n title\n product {\n id\n handle\n title\n images(first: 1) {\n edges {\n node {\n originalSrc\n }\n }\n }\n }\n inventoryQuantity\n inventoryPolicy\n }\n }\n `;\n\n const fullVariantId = `gid://shopify/ProductVariant/${variantId}`;\n console.log(\"SHOP querying with variantId:\", fullVariantId);\n \n const { productVariant } = await shopifyClient.request(gqlQuery, {\n variantId: fullVariantId,\n }) as any;\n\n console.log(\"SHOP productVariant result:\", productVariant);\n\n if (!productVariant) {\n throw new Error(\"Product not found from Shopify\");\n }\n\n const product = {\n image:\n productVariant.image?.originalSrc ||\n productVariant.product.images.edges[0]?.node.originalSrc,\n title: `${productVariant.product.title} - ${productVariant.title}`,\n productId: productVariant.product.id.split(\"/\").pop(),\n variantId: productVariant.id.split(\"/\").pop(),\n price: productVariant.price,\n availableForSale: productVariant.availableForSale,\n inventory: productVariant.inventoryQuantity,\n inventoryTracked: productVariant.inventoryPolicy !== \"deny\",\n productLink: `https://${platform.domain}/admin/products/${productVariant.product.id\n .split(\"/\")\n .pop()}/variants/${productVariant.id.split(\"/\").pop()}`,\n };\n\n return { product };\n}\n\nexport async function searchOrdersFunction({\n platform,\n searchEntry,\n after,\n}: {\n platform: ShopifyPlatform;\n searchEntry: string;\n after?: string;\n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const gqlQuery = gql`\n query SearchOrders($query: String, $after: String) {\n orders(first: 15, query: $query, after: $after) {\n edges {\n node {\n id\n name\n email\n createdAt\n updatedAt\n displayFulfillmentStatus\n displayFinancialStatus\n totalPriceSet {\n presentmentMoney {\n amount\n currencyCode\n }\n }\n shippingAddress {\n firstName\n lastName\n address1\n address2\n city\n province\n provinceCode\n zip\n country\n countryCodeV2\n }\n lineItems(first: 10) {\n edges {\n node {\n id\n title\n quantity\n image {\n originalSrc\n }\n variant {\n id\n title\n price\n sku\n product {\n id\n title\n handle\n }\n }\n }\n }\n }\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n `;\n\n const { orders } = await shopifyClient.request(gqlQuery, {\n query: searchEntry,\n after,\n }) as any;\n\n const formattedOrders = orders.edges.map(({ node, cursor }: any) => ({\n orderId: node.id.split(\"/\").pop(),\n orderName: node.name,\n link: `https://${platform.domain}/admin/orders/${node.id.split(\"/\").pop()}`,\n date: new Date(node.createdAt).toLocaleDateString(),\n firstName: node.shippingAddress?.firstName || \"\",\n lastName: node.shippingAddress?.lastName || \"\",\n streetAddress1: node.shippingAddress?.address1 || \"\",\n streetAddress2: node.shippingAddress?.address2 || \"\",\n city: node.shippingAddress?.city || \"\",\n state: node.shippingAddress?.provinceCode || \"\",\n zip: node.shippingAddress?.zip || \"\",\n country: node.shippingAddress?.countryCodeV2 || \"\",\n email: node.email || \"\",\n fulfillmentStatus: node.displayFulfillmentStatus,\n financialStatus: node.displayFinancialStatus,\n totalPrice: node.totalPriceSet.presentmentMoney.amount,\n currency: node.totalPriceSet.presentmentMoney.currencyCode,\n lineItems: node.lineItems.edges.map(({ node: lineItem }: any) => ({\n lineItemId: lineItem.id.split(\"/\").pop(),\n name: lineItem.title,\n quantity: lineItem.quantity,\n image: lineItem.image?.originalSrc || \"\",\n price: lineItem.variant?.price || \"0\",\n variantId: lineItem.variant?.id.split(\"/\").pop(),\n productId: lineItem.variant?.product.id.split(\"/\").pop(),\n sku: lineItem.variant?.sku || \"\",\n })),\n cartItems: [], // Would be populated if this order has cart items\n fulfillments: [], // Would need to be fetched if needed\n note: \"\",\n cursor,\n }));\n\n return { \n orders: formattedOrders, \n pageInfo: orders.pageInfo \n };\n}\n\nexport async function updateProductFunction({\n platform,\n productId,\n variantId,\n inventory,\n price,\n}: {\n platform: ShopifyPlatform;\n productId: string;\n variantId: string;\n inventory?: number;\n price?: string;\n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const mutations = [];\n\n if (price !== undefined) {\n const updatePriceMutation = gql`\n mutation UpdateProductVariantPrice($input: ProductVariantInput!) {\n productVariantUpdate(input: $input) {\n productVariant {\n id\n price\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n mutations.push(\n shopifyClient.request(updatePriceMutation, {\n input: {\n id: `gid://shopify/ProductVariant/${variantId}`,\n price: price,\n },\n })\n );\n }\n\n if (inventory !== undefined) {\n try {\n // Get current inventory and calculate absolute quantity\n const getVariantWithInventoryQuery = gql`\n query GetVariantWithInventory($id: ID!) {\n productVariant(id: $id) {\n inventoryQuantity\n inventoryItem {\n id\n }\n }\n }\n `;\n\n console.log('QUERYING FOR VARIANT ID:', variantId);\n console.log('FULL GID:', `gid://shopify/ProductVariant/${variantId}`);\n \n const variantData = await shopifyClient.request(getVariantWithInventoryQuery, {\n id: `gid://shopify/ProductVariant/${variantId}`,\n });\n\n console.log('VARIANT DATA RECEIVED:', JSON.stringify(variantData, null, 2));\n\n if (!(variantData as any).productVariant?.inventoryItem?.id) {\n console.log('FAILING BECAUSE NO inventoryItem.id');\n console.log('variantData structure:', variantData);\n console.log('productVariant:', (variantData as any).productVariant);\n console.log('inventoryItem:', (variantData as any).productVariant?.inventoryItem);\n throw new Error(\"Unable to find inventory item for variant\");\n }\n\n // Get the first location\n const getLocationsQuery = gql`\n query GetLocations {\n locations(first: 1) {\n edges {\n node {\n id\n name\n }\n }\n }\n }\n `;\n\n const locationsData = await shopifyClient.request(getLocationsQuery);\n const location = (locationsData as any).locations.edges[0]?.node;\n\n if (!location) {\n throw new Error(\"No locations found for shop\");\n }\n\n // Use inventory delta to adjust available inventory (not on-hand)\n const inventoryDelta = inventory;\n\n const updateInventoryMutation = gql`\n mutation InventoryAdjustQuantities($input: InventoryAdjustQuantitiesInput!) {\n inventoryAdjustQuantities(input: $input) {\n inventoryAdjustmentGroup {\n id\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n mutations.push(\n shopifyClient.request(updateInventoryMutation, {\n input: {\n reason: \"correction\",\n name: \"available\",\n changes: [\n {\n inventoryItemId: (variantData as any).productVariant.inventoryItem.id,\n locationId: location.id, \n delta: inventoryDelta\n }\n ]\n }\n })\n );\n } catch (inventoryError) {\n console.error(\"Error updating inventory:\", inventoryError);\n throw inventoryError;\n }\n }\n\n const results = await Promise.all(mutations);\n return { success: true, results };\n}\n\nexport async function createWebhookFunction({\n platform,\n endpoint,\n events,\n}: {\n platform: ShopifyPlatform;\n endpoint: string;\n events: string[];\n}) {\n\n const mapTopic = {\n ORDER_CREATED: \"ORDERS_CREATE\",\n ORDER_CANCELLED: \"ORDERS_CANCELLED\", \n ORDER_CHARGEBACKED: \"DISPUTES_CREATE\",\n TRACKING_CREATED: \"FULFILLMENTS_CREATE\",\n };\n\n if (!platform.domain) {\n throw new Error(\"Missing domain in platform configuration\");\n }\n\n if (!platform.accessToken) {\n throw new Error(\"Missing accessToken in platform configuration\");\n }\n\n\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const webhooks = [];\n\n for (const event of events) {\n const shopifyTopic = (mapTopic as Record)[event] || event;\n \n const mutation = gql`\n mutation webhookSubscriptionCreate($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) {\n webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) {\n webhookSubscription {\n id\n endpoint {\n __typename\n ... on WebhookHttpEndpoint {\n callbackUrl\n }\n }\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n try {\n const result = await shopifyClient.request(mutation, {\n topic: shopifyTopic,\n webhookSubscription: {\n callbackUrl: endpoint,\n format: \"JSON\",\n },\n }) as any;\n\n\n if (result.webhookSubscriptionCreate.userErrors.length > 0) {\n throw new Error(\n `Error creating webhook: ${result.webhookSubscriptionCreate.userErrors[0].message}`\n );\n }\n\n webhooks.push(result.webhookSubscriptionCreate.webhookSubscription);\n } catch (error) {\n throw error;\n }\n }\n\n // Return the first webhook's ID for compatibility with existing code\n const webhookId = webhooks[0]?.id?.split(\"/\").pop();\n return { webhooks, webhookId };\n}\n\nexport async function deleteWebhookFunction({\n platform,\n webhookId,\n}: {\n platform: ShopifyPlatform;\n webhookId: string;\n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const mutation = gql`\n mutation DeleteWebhook($id: ID!) {\n webhookSubscriptionDelete(id: $id) {\n deletedWebhookSubscriptionId\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const result = await shopifyClient.request(mutation, {\n id: `gid://shopify/WebhookSubscription/${webhookId}`,\n });\n\n return (result as any).webhookSubscriptionDelete;\n}\n\nexport async function getWebhooksFunction({\n platform,\n}: {\n platform: ShopifyPlatform;\n}) {\n const mapTopic = {\n ORDERS_CREATE: \"ORDER_CREATED\",\n ORDERS_CANCELLED: \"ORDER_CANCELLED\",\n DISPUTES_CREATE: \"ORDER_CHARGEBACKED\",\n FULFILLMENTS_CREATE: \"TRACKING_CREATED\",\n };\n\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const query = gql`\n query GetWebhooks {\n webhookSubscriptions(first: 50) {\n edges {\n node {\n id\n topic\n format\n createdAt\n endpoint {\n __typename\n ... on WebhookHttpEndpoint {\n callbackUrl\n }\n }\n }\n }\n }\n }\n `;\n\n const { webhookSubscriptions } = await shopifyClient.request(query) as any;\n\n const baseUrl = await getBaseUrl();\n const webhooks = webhookSubscriptions.edges.map(({ node }: any) => ({\n id: node.id.split(\"/\").pop(),\n callbackUrl: node.endpoint.callbackUrl.replace(baseUrl, \"\"),\n topic: (mapTopic as any)[node.topic] || node.topic,\n format: node.format,\n createdAt: node.createdAt,\n }));\n\n return { webhooks };\n}\n\nexport async function oAuthFunction({\n platform,\n callbackUrl,\n}: {\n platform: ShopifyPlatform;\n callbackUrl: string;\n}) {\n // Use platform's appKey if available, otherwise fall back to env variable for backward compatibility\n const clientId = platform.appKey || process.env.SHOPIFY_APP_KEY;\n \n if (!clientId) {\n throw new Error(\"Shopify OAuth requires appKey in platform config or SHOPIFY_APP_KEY environment variable\");\n }\n \n const scopes = \"read_products,write_products,read_orders,write_orders,read_inventory,write_inventory\";\n const shopifyAuthUrl = `https://${platform.domain}/admin/oauth/authorize?client_id=${clientId}&scope=${scopes}&redirect_uri=${callbackUrl}&state=${Math.random().toString(36).substring(7)}`;\n \n return { authUrl: shopifyAuthUrl };\n}\n\nexport async function oAuthCallbackFunction({\n platform,\n code,\n shop,\n state,\n}: {\n platform: ShopifyPlatform;\n code: string;\n shop: string;\n state: string;\n}) {\n // Use platform credentials if available, otherwise fall back to env variables for backward compatibility\n const clientId = platform.appKey || process.env.SHOPIFY_APP_KEY;\n const clientSecret = platform.appSecret || process.env.SHOPIFY_APP_SECRET;\n \n if (!clientId || !clientSecret) {\n throw new Error(\"Shopify OAuth requires appKey and appSecret in platform config or environment variables\");\n }\n \n const tokenUrl = `https://${shop}/admin/oauth/access_token`;\n \n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n client_id: clientId,\n client_secret: clientSecret,\n code,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\"Failed to exchange OAuth code for access token\");\n }\n\n const { access_token } = await response.json();\n \n return { \n accessToken: access_token,\n domain: shop,\n };\n}\n\nexport async function createOrderWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: ShopifyPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const hmac = headers[\"x-shopify-hmac-sha256\"];\n if (!hmac) {\n throw new Error(\"Missing webhook HMAC\");\n }\n\n // Process the order data and format for Keystone Order creation\n const lineItemsOutput = await Promise.all(\n event.line_items.map(async (item: any) => {\n // Get product variant image from Shopify\n let image = null;\n try {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n 'X-Shopify-Access-Token': platform.accessToken,\n },\n }\n );\n\n const variantQuery = gql`\n query productVariant($id: ID!) {\n productVariant(id: $id) {\n image {\n originalSrc\n }\n product {\n images(first: 1) {\n edges {\n node {\n originalSrc\n }\n }\n }\n }\n }\n }\n `;\n\n const result = await shopifyClient.request(variantQuery, {\n id: `gid://shopify/ProductVariant/${item.variant_id}`,\n });\n\n image = (result as any).productVariant?.image?.originalSrc || \n (result as any).productVariant?.product?.images?.edges?.[0]?.node?.originalSrc || \n null;\n } catch (error) {\n console.warn(`Failed to fetch image for variant ${item.variant_id}:`, error instanceof Error ? error.message : 'Unknown error');\n }\n\n return {\n name: item.title,\n image,\n price: parseFloat(item.price),\n quantity: item.quantity,\n productId: item.product_id?.toString(),\n variantId: item.variant_id?.toString(),\n sku: item.sku || \"\",\n lineItemId: item.id?.toString(),\n };\n })\n );\n\n // Return Keystone-ready order data (same format as Dasher)\n return {\n orderId: event.id?.toString(),\n orderName: event.name,\n email: event.email,\n firstName: event.shipping_address?.first_name,\n lastName: event.shipping_address?.last_name,\n streetAddress1: event.shipping_address?.address1,\n streetAddress2: event.shipping_address?.address2,\n city: event.shipping_address?.city,\n state: event.shipping_address?.province_code,\n zip: event.shipping_address?.zip,\n country: event.shipping_address?.country_code,\n phone: event.shipping_address?.phone,\n currency: event.currency,\n totalPrice: parseFloat(event.total_price),\n subTotalPrice: parseFloat(event.subtotal_price || event.total_price),\n totalDiscounts: parseFloat(event.total_discounts || \"0\"),\n totalTax: parseFloat(event.total_tax || \"0\"),\n status: \"INPROCESS\",\n linkOrder: true,\n matchOrder: true,\n processOrder: true,\n lineItems: { create: lineItemsOutput },\n };\n}\n\nexport async function addTrackingFunction({\n order,\n trackingCompany,\n trackingNumber,\n}: {\n order: any;\n trackingCompany: string;\n trackingNumber: string;\n}) {\n const FETCH_FULFILLMENT_ORDER = gql`\n query ($id: ID!) {\n order(id: $id) {\n fulfillmentOrders(first: 1) {\n edges {\n node {\n id\n status\n fulfillments(first: 1) {\n edges {\n node {\n id\n trackingInfo {\n number\n }\n }\n }\n }\n }\n }\n }\n }\n }\n `;\n\n const UPDATE_FULFILLMENT_TRACKING_INFO = gql`\n mutation fulfillmentTrackingInfoUpdateV2(\n $fulfillmentId: ID!\n $trackingInfoInput: FulfillmentTrackingInput!\n ) {\n fulfillmentTrackingInfoUpdateV2(\n fulfillmentId: $fulfillmentId\n trackingInfoInput: $trackingInfoInput\n ) {\n fulfillment {\n id\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const CREATE_FULFILLMENT = gql`\n mutation fulfillmentCreateV2($fulfillment: FulfillmentV2Input!) {\n fulfillmentCreateV2(fulfillment: $fulfillment) {\n fulfillment {\n id\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n \n const client = new GraphQLClient(\n `https://${order.shop.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Shopify-Access-Token\": order.shop.accessToken,\n },\n }\n );\n\n const data = await client.request(FETCH_FULFILLMENT_ORDER, {\n id: `gid://shopify/Order/${order.orderId}`,\n }) as any;\n\n const fulfillmentOrder = data.order?.fulfillmentOrders?.edges?.[0]?.node;\n \n if (!fulfillmentOrder) {\n throw new Error(\"No fulfillment order found\");\n }\n\n if (fulfillmentOrder.status === \"CLOSED\") {\n const fulfillment = fulfillmentOrder.fulfillments.edges[0]?.node;\n if (fulfillment) {\n const updateResponseBody = await client.request(\n UPDATE_FULFILLMENT_TRACKING_INFO,\n {\n fulfillmentId: fulfillment.id,\n trackingInfoInput: {\n numbers: [\n trackingNumber,\n ...fulfillment.trackingInfo.map(({ number }: any) => number),\n ],\n },\n }\n );\n return updateResponseBody;\n }\n }\n\n const createResponseBody = await client.request(CREATE_FULFILLMENT, {\n fulfillment: {\n lineItemsByFulfillmentOrder: [\n {\n fulfillmentOrderId: fulfillmentOrder.id,\n },\n ],\n trackingInfo: {\n company: trackingCompany,\n numbers: [trackingNumber],\n },\n },\n });\n\n return createResponseBody;\n}\n\nexport async function cancelOrderWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: ShopifyPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const hmac = headers[\"x-shopify-hmac-sha256\"];\n if (!hmac) {\n throw new Error(\"Missing webhook HMAC\");\n }\n\n const order = {\n id: event.id,\n name: event.name,\n cancelReason: event.cancel_reason,\n cancelledAt: event.cancelled_at,\n };\n\n return { order, type: \"order_cancelled\" };\n}\n\n// Required OAuth scopes for Shopify shop integration\nconst REQUIRED_SCOPES = \"read_products,write_products,read_orders,write_orders,read_inventory,write_inventory\";\n\nexport function scopes() {\n return REQUIRED_SCOPES;\n}", "export async function executeShopAdapterFunction({ platform, functionName, args }: { platform: any; functionName: string; args: any }) {\n const functionPath = platform[functionName];\n\n if (functionPath.startsWith(\"http\")) {\n const response = await fetch(functionPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform, ...args }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP request failed: ${response.statusText}`);\n }\n return response.json();\n }\n\n const adapter = await import(\n `../${functionPath}.ts`\n );\n\n const fn = adapter[functionName];\n if (!fn) {\n throw new Error(\n `Function ${functionName} not found in adapter ${functionPath}`\n );\n }\n\n try {\n return await fn({ platform, ...args });\n } catch (error) {\n throw new Error(\n `Error executing ${functionName} for platform ${functionPath}: ${(error as Error).message}`\n );\n }\n}\n\n// Helper functions for common shop operations\nexport async function searchShopProducts({ platform, searchEntry, after }: { platform: any; searchEntry: string; after?: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"searchProductsFunction\",\n args: { searchEntry, after },\n });\n}\n\nexport async function getShopProduct({ platform, productId }: { platform: any; productId: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"getProductFunction\",\n args: { productId },\n });\n}\n\nexport async function searchShopOrders({ platform, searchEntry, after }: { platform: any; searchEntry: string; after?: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"searchOrdersFunction\",\n args: { searchEntry, after },\n });\n}\n\nexport async function updateShopProduct({ platform, productId, inventory, price }: { platform: any; productId: string; inventory?: number; price?: number }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"updateProductFunction\",\n args: { productId, inventory, price },\n });\n}\n\nexport async function addCartToPlatformOrder({ platform, cartItems, orderId }: { platform: any; cartItems: any; orderId: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"addCartToPlatformOrderFunction\",\n args: { cartItems, orderId },\n });\n}\n\nexport async function createShopWebhook({ platform, endpoint, events }: { platform: any; endpoint: string; events: string[] }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"createWebhookFunction\",\n args: { endpoint, events },\n });\n}\n\nexport async function deleteShopWebhook({ platform, webhookId }: { platform: any; webhookId: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"deleteWebhookFunction\",\n args: { webhookId },\n });\n}\n\nexport async function getShopWebhooks({ platform }: { platform: any }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"getWebhooksFunction\",\n args: {},\n });\n}\n\nexport async function handleShopOAuth({ platform, callbackUrl }: { platform: any; callbackUrl: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"oAuthFunction\",\n args: { callbackUrl },\n });\n}\n\nexport async function handleShopOAuthCallback({ platform, code, shop, state, appKey, appSecret, redirectUri }: { platform: any; code?: string; shop?: string; state?: string; appKey?: string; appSecret?: string; redirectUri?: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"oAuthCallbackFunction\",\n args: { code, shop, state, appKey, appSecret, redirectUri },\n });\n}\n\nexport async function handleShopOrderWebhook({ platform, event, headers }: { platform: any; event: any; headers: any }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"createOrderWebhookHandler\",\n args: { event, headers },\n });\n}\n\nexport async function handleShopCancelWebhook({ platform, event, headers }: { platform: any; event: any; headers: any }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"cancelOrderWebhookHandler\",\n args: { event, headers },\n });\n}\n\nexport async function addShopTracking({ platform, order, trackingCompany, trackingNumber }: { platform: any; order: any; trackingCompany: string; trackingNumber: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"addTrackingFunction\",\n args: { order, trackingCompany, trackingNumber },\n });\n}", "// keystone.ts - Main entry point for Keystone\nimport config from './features/keystone';\n\nexport default config;", "import { createAuth } from \"@keystone-6/auth\";\nimport { config } from \"@keystone-6/core\";\nimport \"dotenv/config\";\nimport { models } from \"./models\";\nimport { extendGraphqlSchema } from \"./extendGraphqlSchema\";\nimport { permissionsList } from \"./models/fields\";\nimport { sendPasswordResetEmail } from \"./lib/mail\";\nimport Iron from \"@hapi/iron\";\nimport * as cookie from \"cookie\";\nimport { hashApiKeySync } from \"./lib/crypto-utils\";\nimport bcryptjs from \"bcryptjs\";\n\nconst databaseURL = process.env.DATABASE_URL || \"file:./keystone.db\";\n\nconst sessionConfig = {\n maxAge: 60 * 60 * 24 * 360, // How long they stay signed in?\n secret:\n process.env.SESSION_SECRET || \"this secret should only be used in testing\",\n};\n\nconst listKey = \"User\";\n\nexport function statelessSessions({\n secret,\n maxAge = 60 * 60 * 24 * 360,\n path = \"/\",\n secure = process.env.NODE_ENV === \"production\",\n ironOptions = Iron.defaults,\n domain,\n sameSite = \"lax\" as const,\n cookieName = \"keystonejs-session\",\n}: {\n secret: string;\n maxAge?: number;\n path?: string;\n secure?: boolean;\n ironOptions?: any;\n domain?: string;\n sameSite?: \"lax\" | \"none\" | \"strict\" | boolean;\n cookieName?: string;\n}) {\n if (!secret) {\n throw new Error(\"You must specify a session secret to use sessions\");\n }\n if (secret.length < 32) {\n throw new Error(\"The session secret must be at least 32 characters long\");\n }\n\n return {\n async get({ context }: { context: any }) {\n if (!context?.req) return;\n \n // Check for OAuth Bearer token authentication\n const authHeader = context.req.headers.authorization;\n console.log('\uD83D\uDD11 AUTH HEADER:', authHeader);\n \n if (authHeader?.startsWith(\"Bearer \")) {\n const accessToken = authHeader.replace(\"Bearer \", \"\");\n console.log('\uD83D\uDD11 ACCESS TOKEN:', accessToken);\n \n // Try to validate as API key first\n if (accessToken.startsWith(\"osp_\")) {\n console.log('\uD83D\uDD11 API KEY DETECTED, VALIDATING...');\n try {\n // Get all active API keys and test the token against each one\n const apiKeys = await context.sudo().query.ApiKey.findMany({\n where: { status: { equals: 'active' } },\n query: `\n id\n name\n scopes\n status\n expiresAt\n usageCount\n tokenSecret { isSet }\n user { id }\n `,\n });\n \n console.log('\uD83D\uDD11 CHECKING AGAINST', apiKeys.length, 'ACTIVE API KEYS');\n \n let matchingApiKey = null;\n \n // Test token against each API key using bcryptjs (same as Keystone's default KDF)\n for (const apiKey of apiKeys) {\n try {\n if (!apiKey.tokenSecret?.isSet) continue;\n \n // Get the full API key item with the tokenSecret value\n const fullApiKey = await context.sudo().db.ApiKey.findOne({\n where: { id: apiKey.id },\n });\n \n if (!fullApiKey || typeof fullApiKey.tokenSecret !== 'string') {\n continue;\n }\n \n // Use bcryptjs to compare - this is exactly what Keystone does internally\n const isValid = await bcryptjs.compare(accessToken, fullApiKey.tokenSecret);\n \n if (isValid) {\n matchingApiKey = apiKey;\n console.log('\uD83D\uDD11 FOUND MATCHING API KEY:', apiKey.id);\n break;\n }\n } catch (error) {\n console.log('\uD83D\uDD11 ERROR VERIFYING API KEY:', error);\n // Continue to next API key if this one doesn't match\n continue;\n }\n }\n \n if (!matchingApiKey) {\n console.log('\uD83D\uDD11 NO MATCHING API KEY FOUND');\n return; // API key not found or invalid\n }\n \n if (matchingApiKey.status !== 'active') {\n console.log('\uD83D\uDD11 API KEY NOT ACTIVE:', matchingApiKey.status);\n return; // API key is inactive\n }\n \n if (matchingApiKey.expiresAt && new Date() > new Date(matchingApiKey.expiresAt)) {\n console.log('\uD83D\uDD11 API KEY EXPIRED');\n // Auto-revoke expired keys\n await context.sudo().query.ApiKey.updateOne({\n where: { id: matchingApiKey.id },\n data: { status: 'revoked' },\n });\n return; // API key has expired\n }\n \n // Update usage statistics (async, don't wait)\n const today = new Date().toISOString().split('T')[0];\n const usage = matchingApiKey.usageCount || { total: 0, daily: {} };\n usage.total = (usage.total || 0) + 1;\n usage.daily[today] = (usage.daily[today] || 0) + 1;\n \n context.sudo().query.ApiKey.updateOne({\n where: { id: matchingApiKey.id },\n data: {\n lastUsedAt: new Date(),\n usageCount: usage,\n },\n }).catch(console.error);\n \n // Return user session with API key scopes attached\n if (matchingApiKey.user?.id) {\n const session = { \n itemId: matchingApiKey.user.id, \n listKey,\n apiKeyScopes: matchingApiKey.scopes || [] // Attach scopes for permission checking\n };\n console.log('\uD83D\uDD11 RETURNING SESSION:', JSON.stringify(session, null, 2));\n return session;\n }\n } catch (err) {\n console.log('\uD83D\uDD11 API Key validation error:', err);\n return;\n }\n }\n \n // If not API key, try as regular session token\n try {\n return await Iron.unseal(accessToken, secret, ironOptions);\n } catch (err) {}\n }\n \n // Check for session cookie\n const cookies = cookie.parse(context.req.headers.cookie || \"\");\n const token = cookies[cookieName];\n if (!token) return;\n try {\n return await Iron.unseal(token, secret, ironOptions);\n } catch (err) {}\n },\n async end({ context }: { context: any }) {\n if (!context?.res) return;\n\n context.res.setHeader(\n \"Set-Cookie\",\n cookie.serialize(cookieName, \"\", {\n maxAge: 0,\n expires: new Date(),\n httpOnly: true,\n secure,\n path,\n sameSite,\n domain,\n })\n );\n },\n async start({ context, data }: { context: any; data: any }) {\n if (!context?.res) return;\n\n const sealedData = await Iron.seal(data, secret, {\n ...ironOptions,\n ttl: maxAge * 1000,\n });\n context.res.setHeader(\n \"Set-Cookie\",\n cookie.serialize(cookieName, sealedData, {\n maxAge,\n expires: new Date(Date.now() + maxAge * 1000),\n httpOnly: true,\n secure,\n path,\n sameSite,\n domain,\n })\n );\n\n return sealedData;\n },\n };\n}\n\nconst { withAuth } = createAuth({\n listKey,\n identityField: \"email\",\n secretField: \"password\",\n initFirstItem: {\n fields: [\"name\", \"email\", \"password\"],\n itemData: {\n role: {\n create: {\n name: \"Admin\",\n canSeeOtherUsers: true,\n canEditOtherUsers: true,\n canManageUsers: true,\n canManageRoles: true,\n canAccessDashboard: true,\n canSeeOtherShops: true,\n canManageShops: true,\n canCreateShops: true,\n canSeeOtherChannels: true,\n canManageChannels: true,\n canCreateChannels: true,\n canSeeOtherOrders: true,\n canManageOrders: true,\n canProcessOrders: true,\n canSeeOtherMatches: true,\n canManageMatches: true,\n canCreateMatches: true,\n canSeeOtherLinks: true,\n canManageLinks: true,\n canCreateLinks: true,\n canManagePlatforms: true,\n canViewPlatformMetrics: true,\n canManageApiKeys: true,\n canCreateApiKeys: true,\n canAccessAnalytics: true,\n canExportData: true,\n canManageWebhooks: true,\n },\n },\n },\n },\n passwordResetLink: {\n async sendToken(args) {\n // send the email\n await sendPasswordResetEmail(args.token, args.identity);\n },\n },\n sessionData: `id name email role { id name ${permissionsList.join(\" \")} }`,\n});\n\nexport default withAuth(\n config({\n db: {\n provider: \"postgresql\",\n url: databaseURL,\n },\n lists: models,\n ui: {\n isAccessAllowed: ({ session }) => session?.data.role?.canAccessDashboard ?? false,\n },\n session: statelessSessions(sessionConfig),\n graphql: {\n extendGraphqlSchema,\n },\n })\n);", "import { list } from \"@keystone-6/core\";\nimport { allOperations, denyAll } from \"@keystone-6/core/access\";\nimport {\n checkbox,\n password,\n relationship,\n text,\n timestamp,\n} from \"@keystone-6/core/fields\";\n\nimport {\n isSignedIn,\n permissions,\n rules,\n itemRules,\n fieldRules,\n} from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const User = list({\n access: {\n operation: {\n query: isSignedIn,\n create: permissions.canManageUsers,\n update: isSignedIn,\n delete: permissions.canManageUsers,\n },\n filter: {\n query: rules.canReadPeople,\n update: rules.canUpdatePeople,\n delete: rules.canUpdatePeople,\n },\n item: {\n update: itemRules.canUpdateUser,\n delete: itemRules.canDeleteUser,\n },\n },\n ui: {\n hideCreate: (args: any) => !permissions.canManageUsers({ session: args.session, context: args.context, listKey: 'User', operation: 'create' }),\n hideDelete: (args: any) => !permissions.canManageUsers({ session: args.session, context: args.context, listKey: 'User', operation: 'delete' }),\n listView: {\n initialColumns: [\"name\", \"email\", \"role\", \"shops\", \"channels\"],\n },\n itemView: {\n defaultFieldMode: ({ session, item }) => {\n // canEditOtherUsers can edit other people\n if (session?.data.role?.canEditOtherUsers) return \"edit\";\n\n // edit themselves\n if (session?.itemId === item?.id) return \"edit\";\n\n // else, default all fields to read mode\n return \"read\";\n },\n },\n },\n fields: {\n name: text({\n validation: {\n isRequired: true,\n },\n }),\n email: text({\n isFilterable: false,\n isOrderable: false,\n isIndexed: \"unique\",\n validation: {\n isRequired: true,\n },\n }),\n password: password({\n access: {\n read: fieldRules.canReadUserPassword,\n update: fieldRules.canUpdateUserPassword,\n },\n validation: { isRequired: true },\n }),\n role: relationship({\n ref: \"Role.assignedTo\",\n access: {\n create: fieldRules.canManageUserRole,\n update: fieldRules.canManageUserRole,\n },\n ui: {\n itemView: {\n fieldMode: (args: any) =>\n permissions.canManageUsers({ session: args.session, context: args.context, listKey: 'User', operation: 'update' }) ? \"edit\" : \"read\",\n },\n },\n }),\n\n // E-commerce Platform Management Relationships\n shops: relationship({\n ref: \"Shop.user\",\n many: true,\n }),\n channels: relationship({\n ref: \"Channel.user\",\n many: true,\n }),\n orders: relationship({\n ref: \"Order.user\",\n many: true,\n }),\n lineItems: relationship({\n ref: \"LineItem.user\",\n many: true,\n }),\n cartItems: relationship({\n ref: \"CartItem.user\",\n many: true,\n }),\n shopItems: relationship({\n ref: \"ShopItem.user\",\n many: true,\n }),\n channelItems: relationship({\n ref: \"ChannelItem.user\",\n many: true,\n }),\n matches: relationship({\n ref: \"Match.user\",\n many: true,\n }),\n links: relationship({\n ref: \"Link.user\",\n many: true,\n }),\n trackingDetails: relationship({\n ref: \"TrackingDetail.user\",\n many: true,\n }),\n shopPlatforms: relationship({\n ref: \"ShopPlatform.user\",\n many: true,\n }),\n channelPlatforms: relationship({\n ref: \"ChannelPlatform.user\",\n many: true,\n }),\n apiKeys: relationship({\n ref: \"ApiKey.user\",\n many: true,\n }),\n\n ...trackingFields,\n },\n});\n", "/**\n * API Key Scopes to Permission Mapping\n * \n * This file maps API key scopes (used by external integrations) to internal permissions.\n * When an API key has a certain scope, it grants the mapped permissions.\n */\n\nimport type { ApiKeyScope } from '../models/ApiKey';\n\nexport type OpenseaPermission = \n | \"canSeeOtherUsers\"\n | \"canEditOtherUsers\"\n | \"canManageUsers\"\n | \"canManageRoles\"\n | \"canAccessDashboard\"\n | \"canSeeOtherShops\"\n | \"canManageShops\"\n | \"canCreateShops\"\n | \"canSeeOtherChannels\"\n | \"canManageChannels\"\n | \"canCreateChannels\"\n | \"canSeeOtherOrders\"\n | \"canManageOrders\"\n | \"canProcessOrders\"\n | \"canSeeOtherMatches\"\n | \"canManageMatches\"\n | \"canCreateMatches\"\n | \"canSeeOtherLinks\"\n | \"canManageLinks\"\n | \"canCreateLinks\"\n | \"canManagePlatforms\"\n | \"canViewPlatformMetrics\"\n | \"canManageApiKeys\"\n | \"canCreateApiKeys\"\n | \"canAccessAnalytics\"\n | \"canExportData\"\n | \"canManageWebhooks\";\n\n/**\n * Maps API key scopes to internal permissions\n */\nexport const SCOPE_TO_PERMISSIONS: Record = {\n // Orders\n \"read_orders\": [\"canSeeOtherOrders\"],\n \"write_orders\": [\"canSeeOtherOrders\", \"canManageOrders\", \"canProcessOrders\"],\n \n // Products (these don't have direct permissions but follow the pattern)\n \"read_products\": [],\n \"write_products\": [],\n \n // Shops\n \"read_shops\": [\"canSeeOtherShops\"],\n \"write_shops\": [\"canSeeOtherShops\", \"canManageShops\", \"canCreateShops\"],\n \n // Channels\n \"read_channels\": [\"canSeeOtherChannels\"],\n \"write_channels\": [\"canSeeOtherChannels\", \"canManageChannels\", \"canCreateChannels\"],\n \n // Matches\n \"read_matches\": [\"canSeeOtherMatches\"],\n \"write_matches\": [\"canSeeOtherMatches\", \"canManageMatches\", \"canCreateMatches\"],\n \n // Links\n \"read_links\": [\"canSeeOtherLinks\"],\n \"write_links\": [\"canSeeOtherLinks\", \"canManageLinks\", \"canCreateLinks\"],\n \n // Platforms\n \"read_platforms\": [\"canViewPlatformMetrics\"],\n \"write_platforms\": [\"canViewPlatformMetrics\", \"canManagePlatforms\"],\n \n // Webhooks\n \"read_webhooks\": [\"canManageWebhooks\"], // Read webhooks requires manage permission\n \"write_webhooks\": [\"canManageWebhooks\"],\n \n // Analytics\n \"read_analytics\": [\"canAccessAnalytics\", \"canExportData\"],\n \n // Users\n \"read_users\": [\"canSeeOtherUsers\"],\n \"write_users\": [\"canSeeOtherUsers\", \"canEditOtherUsers\", \"canManageUsers\", \"canManageRoles\"],\n};\n\n/**\n * Gets all permissions for a given set of API key scopes\n */\nexport function getPermissionsForApiKeyScopes(scopes: ApiKeyScope[]): OpenseaPermission[] {\n const permissions = new Set();\n \n scopes.forEach(scope => {\n const scopePermissions = SCOPE_TO_PERMISSIONS[scope];\n if (scopePermissions) {\n scopePermissions.forEach(permission => permissions.add(permission));\n }\n });\n \n return Array.from(permissions);\n}\n\n/**\n * Checks if a set of API key scopes grants a specific permission\n */\nexport function hasApiKeyPermission(scopes: ApiKeyScope[], permission: OpenseaPermission): boolean {\n return getPermissionsForApiKeyScopes(scopes).includes(permission);\n}\n\n/**\n * Helper function to check if API key scopes grant a permission\n */\nexport function checkApiKeyPermission(session: any, permission: OpenseaPermission): boolean {\n if (!session?.apiKeyScopes) return false;\n \n const scopes = session.apiKeyScopes as ApiKeyScope[];\n return hasApiKeyPermission(scopes, permission);\n}", "// Keystone 6 Access Control - Following Official Documentation\n// https://keystonejs.com/docs/config/access-control\n\nimport { checkApiKeyPermission, type OpenseaPermission } from './lib/api-key-scopes';\n\nexport type Session = {\n itemId: string\n listKey: string\n data: {\n id: string\n name: string\n email: string\n role: {\n id: string\n name: string\n // Basic Dashboard Permissions\n canSeeOtherUsers: boolean\n canEditOtherUsers: boolean\n canManageUsers: boolean\n canManageRoles: boolean\n canAccessDashboard: boolean\n \n // E-commerce Platform Permissions\n // Shop Management\n canSeeOtherShops: boolean\n canManageShops: boolean\n canCreateShops: boolean\n \n // Channel Management\n canSeeOtherChannels: boolean\n canManageChannels: boolean\n canCreateChannels: boolean\n \n // Order Management\n canSeeOtherOrders: boolean\n canManageOrders: boolean\n canProcessOrders: boolean\n \n // Product & Inventory Management\n canSeeOtherMatches: boolean\n canManageMatches: boolean\n canCreateMatches: boolean\n \n // Linking System\n canSeeOtherLinks: boolean\n canManageLinks: boolean\n canCreateLinks: boolean\n \n // Platform Integration\n canManagePlatforms: boolean\n canViewPlatformMetrics: boolean\n \n // API Key Management\n canManageApiKeys: boolean\n canCreateApiKeys: boolean\n \n // Advanced Features\n canAccessAnalytics: boolean\n canExportData: boolean\n canManageWebhooks: boolean\n }\n }\n}\n\n// Standard Keystone Access Control Arguments\ntype OperationAccessArgs = {\n session?: Session\n context: any\n listKey: string\n operation: string\n}\n\ntype FilterAccessArgs = {\n session?: Session\n context: any\n listKey: string\n operation: string\n}\n\ntype ItemAccessArgs = {\n session?: Session\n context: any\n listKey: string\n operation: string\n inputData?: any\n item?: any\n}\n\ntype FieldAccessArgs = {\n session?: Session\n context: any\n listKey: string\n fieldKey: string\n operation: string\n inputData?: any\n item?: any\n}\n\n// Basic Authentication Check\nexport const isSignedIn = ({ session }: OperationAccessArgs): boolean => {\n return Boolean(session)\n}\n\n// Helper function to check if API key scopes or role grants a permission\nfunction hasPermission(session: any, permission: OpenseaPermission): boolean {\n // If this is an API key session, ONLY check API key scopes\n if (session?.apiKeyScopes) {\n return checkApiKeyPermission(session, permission);\n }\n // Otherwise, check role-based permissions for regular user sessions\n return Boolean(session?.data?.role?.[permission]);\n}\n\n// Permission Functions - Operation Level Access Control\nexport const permissions = {\n // Basic Dashboard Permissions\n canSeeOtherUsers: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canSeeOtherUsers),\n \n canEditOtherUsers: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canEditOtherUsers),\n \n canManageUsers: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageUsers),\n \n canManageRoles: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageRoles),\n \n canAccessDashboard: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canAccessDashboard),\n \n // E-commerce Platform Permissions\n // Shop Management\n canSeeOtherShops: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canSeeOtherShops\"),\n \n canManageShops: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canManageShops\"),\n \n canCreateShops: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canCreateShops\"),\n \n // Channel Management\n canSeeOtherChannels: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canSeeOtherChannels\"),\n \n canManageChannels: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canManageChannels\"),\n \n canCreateChannels: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canCreateChannels\"),\n \n canUpdateChannels: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageChannels),\n \n // Order Management\n canSeeOtherOrders: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canSeeOtherOrders),\n \n canManageOrders: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageOrders),\n \n canProcessOrders: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canProcessOrders),\n \n // Product & Inventory Management\n canSeeOtherMatches: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canSeeOtherMatches),\n \n canManageMatches: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageMatches),\n \n canCreateMatches: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canCreateMatches),\n \n // Linking System\n canSeeOtherLinks: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canSeeOtherLinks),\n \n canManageLinks: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageLinks),\n \n canCreateLinks: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canCreateLinks),\n \n // Platform Integration\n canManagePlatforms: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManagePlatforms),\n \n canViewPlatformMetrics: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canViewPlatformMetrics),\n \n // API Key Management\n canManageApiKeys: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageApiKeys),\n \n canCreateApiKeys: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canCreateApiKeys),\n \n // Advanced Features\n canAccessAnalytics: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canAccessAnalytics),\n \n canExportData: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canExportData),\n \n canManageWebhooks: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageWebhooks),\n}\n\n// Filter Rules - Filter Level Access Control\nexport const rules = {\n // User Rules\n canReadPeople: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n\n // Admin can see all users\n if (session.data.role?.canSeeOtherUsers) return true\n\n // Users can only see themselves\n return { id: { equals: session.itemId } }\n },\n \n canUpdatePeople: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n\n // Admin can edit all users\n if (session.data.role?.canEditOtherUsers) return true\n\n // Users can only edit themselves\n return { id: { equals: session.itemId } }\n },\n \n // E-commerce Multi-tenant Rules\n // Shop Rules - users can only access their own shops unless they have permission\n canReadShops: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all shops\n if (session.data.role?.canSeeOtherShops) return true\n \n // Users can only see their own shops\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageShops: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all shops\n if (session.data.role?.canManageShops) return true\n \n // Users can only manage their own shops\n return { user: { id: { equals: session.itemId } } }\n },\n \n // Channel Rules\n canReadChannels: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all channels\n if (session.data.role?.canSeeOtherChannels) return true\n \n // Users can only see their own channels\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageChannels: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all channels\n if (session.data.role?.canManageChannels) return true\n \n // Users can only manage their own channels\n return { user: { id: { equals: session.itemId } } }\n },\n \n canUpdateChannels: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can update all channels\n if (session.data.role?.canManageChannels) return true\n \n // Users can only update their own channels\n return { user: { id: { equals: session.itemId } } }\n },\n \n // Order Rules\n canReadOrders: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all orders\n if (session.data.role?.canSeeOtherOrders) return true\n \n // Users can only see their own orders\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageOrders: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all orders\n if (session.data.role?.canManageOrders) return true\n \n // Users can only manage their own orders\n return { user: { id: { equals: session.itemId } } }\n },\n \n // Match Rules (Product Matching)\n canReadMatches: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all matches\n if (session.data.role?.canSeeOtherMatches) return true\n \n // Users can only see their own matches\n return { user: { id: { equals: session.itemId } } }\n },\n \n canUpdateMatches: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all matches\n if (session.data.role?.canManageMatches) return true\n \n // Users can only manage their own matches\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageMatches: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all matches\n if (session.data.role?.canManageMatches) return true\n \n // Users can only manage their own matches\n return { user: { id: { equals: session.itemId } } }\n },\n \n // Link Rules (Shop-Channel Linking)\n canReadLinks: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all links\n if (session.data.role?.canSeeOtherLinks) return true\n \n // Users can only see their own links\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageLinks: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all links\n if (session.data.role?.canManageLinks) return true\n \n // Users can only manage their own links\n return { user: { id: { equals: session.itemId } } }\n },\n\n // API Key Rules\n canReadApiKeys: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all API keys\n if (session.data.role?.canManageApiKeys) return true\n \n // Users can only see their own API keys\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageApiKeys: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all API keys\n if (session.data.role?.canManageApiKeys) return true\n \n // Users can only manage their own API keys\n return { user: { id: { equals: session.itemId } } }\n },\n}\n\n// Item-Level Access Control Functions\nexport const itemRules = {\n canUpdateUser: ({ session, item }: ItemAccessArgs): boolean => {\n if (!session) return false\n \n // Admin can edit any user\n if (session.data.role?.canEditOtherUsers) return true\n \n // Users can only edit themselves\n return session.itemId === item.id\n },\n \n canDeleteUser: ({ session }: ItemAccessArgs): boolean => {\n if (!session) return false\n \n // Only admin can delete users\n return Boolean(session.data.role?.canManageUsers)\n },\n}\n\n// Field-Level Access Control Functions\nexport const fieldRules = {\n canReadUserPassword: (): boolean => false, // Never allow reading passwords\n \n canUpdateUserPassword: ({ session, item }: FieldAccessArgs): boolean => {\n if (!session) return false\n \n // Admin can update any password\n if (session.data.role?.canManageUsers) return true\n \n // Users can only update their own password\n return session.itemId === item?.id\n },\n \n canManageUserRole: ({ session }: FieldAccessArgs): boolean => {\n if (!session) return false\n \n // Only admin can manage roles\n return Boolean(session.data.role?.canManageUsers)\n },\n}", "import { timestamp } from \"@keystone-6/core/fields\";\n\nexport const trackingFields = {\n createdAt: timestamp({\n access: { read: () => true, create: () => false, update: () => false },\n validation: { isRequired: true },\n defaultValue: { kind: \"now\" },\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n },\n hooks: {\n resolveInput: ({ context, operation, resolvedData }) => {\n if (operation === \"create\") return new Date();\n return resolvedData.createdAt;\n },\n },\n }),\n updatedAt: timestamp({\n access: { read: () => true, create: () => false, update: () => false },\n // db: { updatedAt: true },\n validation: { isRequired: true },\n defaultValue: { kind: \"now\" },\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n },\n hooks: {\n resolveInput: ({ context, operation, resolvedData }) => {\n if (operation === \"update\") return new Date();\n return resolvedData.updatedAt;\n },\n },\n }),\n};", "import {\n text,\n password,\n relationship,\n multiselect,\n select,\n timestamp,\n json,\n} from \"@keystone-6/core/fields\";\nimport { list } from \"@keystone-6/core\";\nimport { isSignedIn, rules, permissions } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { generateApiKeyTokenSync, hashApiKeySync } from \"../lib/crypto-utils\";\n\n// Define available API key scopes (using underscore format like OpenFront)\nexport const API_KEY_SCOPES = {\n // Orders\n \"read_orders\": \"View orders\",\n \"write_orders\": \"Manage orders\",\n \n // Products \n \"read_products\": \"View products\",\n \"write_products\": \"Manage products\",\n \n // Shops\n \"read_shops\": \"View shops\", \n \"write_shops\": \"Manage shops\",\n \n // Channels\n \"read_channels\": \"View channels\",\n \"write_channels\": \"Manage channels\",\n \n // Matches\n \"read_matches\": \"View product matches\",\n \"write_matches\": \"Manage product matches\",\n \n // Links\n \"read_links\": \"View automation links\",\n \"write_links\": \"Manage automation links\",\n \n // Platforms\n \"read_platforms\": \"View platform configurations\",\n \"write_platforms\": \"Manage platform configurations\",\n \n // Webhooks\n \"read_webhooks\": \"View webhook configurations\",\n \"write_webhooks\": \"Manage webhook configurations\",\n \n // Analytics\n \"read_analytics\": \"View analytics data\",\n \n // Users\n \"read_users\": \"View users\",\n \"write_users\": \"Manage users and permissions\",\n} as const;\n\nexport type ApiKeyScope = keyof typeof API_KEY_SCOPES;\n\n// Generate secure API key token\nfunction generateApiKeyToken(): string {\n return generateApiKeyTokenSync();\n}\n\n// Hash API key for secure storage\nfunction hashApiKey(key: string): string {\n return hashApiKeySync(key);\n}\n\nexport const ApiKey = list({\n access: {\n operation: {\n query: isSignedIn,\n create: permissions.canCreateApiKeys,\n update: permissions.canManageApiKeys,\n delete: permissions.canManageApiKeys,\n },\n filter: {\n query: rules.canReadApiKeys,\n update: rules.canManageApiKeys,\n delete: rules.canManageApiKeys,\n },\n },\n hooks: {\n validate: {\n create: async ({ resolvedData, addValidationError }) => {\n if (!resolvedData.scopes || resolvedData.scopes.length === 0) {\n addValidationError('At least one scope is required for API keys');\n }\n },\n },\n resolveInput: {\n create: async ({ resolvedData, context }) => {\n // Auto-assign user relationship\n return {\n ...resolvedData,\n user: resolvedData.user || (context.session?.itemId ? { connect: { id: context.session.itemId } } : undefined),\n };\n },\n },\n },\n fields: {\n name: text({\n validation: { isRequired: true },\n ui: {\n description: \"A descriptive name for this API key (e.g. 'Production Bot', 'Analytics Dashboard')\",\n },\n }),\n \n tokenSecret: password({\n validation: { isRequired: true },\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"hidden\" },\n listView: { fieldMode: \"hidden\" },\n description: \"Secure API key token (hashed and never displayed)\",\n },\n }),\n \n tokenPreview: text({\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n listView: { fieldMode: \"read\" },\n description: \"Preview of the API key (actual key is hidden for security)\",\n },\n }),\n \n scopes: json({\n defaultValue: [],\n ui: {\n description: \"Array of scopes for this API key. Available scopes: orders:read, orders:write, shops:read, shops:write, channels:read, channels:write, etc.\",\n },\n }),\n \n status: select({\n type: 'enum',\n options: [\n { label: \"Active\", value: \"active\" },\n { label: \"Inactive\", value: \"inactive\" },\n { label: \"Revoked\", value: \"revoked\" },\n ],\n defaultValue: \"active\",\n ui: {\n description: \"Current status of this API key\",\n },\n }),\n \n expiresAt: timestamp({\n ui: {\n description: \"When this API key expires (optional - leave blank for no expiration)\",\n },\n }),\n \n lastUsedAt: timestamp({\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n description: \"Last time this API key was used\",\n },\n }),\n \n usageCount: json({\n defaultValue: { total: 0, daily: {} },\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n description: \"Usage statistics for this API key\",\n },\n }),\n \n restrictedToIPs: json({\n defaultValue: [],\n ui: {\n description: \"Optional: Restrict this key to specific IP addresses (array of IPs)\",\n },\n }),\n \n user: relationship({\n ref: \"User.apiKeys\",\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n },\n }),\n \n ...trackingFields,\n },\n \n ui: {\n labelField: \"name\",\n listView: {\n initialColumns: [\"name\", \"tokenPreview\", \"scopes\", \"status\", \"lastUsedAt\", \"expiresAt\"],\n },\n description: \"Secure API keys for programmatic access to Openship\",\n },\n});\n\n// Helper function to validate API key tokens using password field\nexport async function validateApiKeyToken(\n apiKeyId: string,\n token: string,\n context: any\n): Promise {\n try {\n // Use Keystone's built-in password verification through createAuth\n // This is a simplified approach - we'll handle this in the authentication layer\n const result = await context.query.ApiKey.authenticateItemWithPassword({\n identifier: apiKeyId,\n secret: token,\n identityField: 'id',\n secretField: 'tokenSecret'\n });\n \n return result.success;\n } catch (error) {\n return false;\n }\n}\n\n// Simplified validation function for API keys\nexport async function validateApiKey(\n token: string,\n requiredScopes: ApiKeyScope[] = [],\n context: any\n): Promise<{\n valid: boolean;\n user?: any;\n scopes?: ApiKeyScope[];\n error?: string;\n}> {\n if (!token || !token.startsWith('osp_')) {\n return { valid: false, error: 'Invalid API key format' };\n }\n \n // This will be handled differently - we'll need to update the keystone/index.ts\n // authentication logic to use the password field directly\n // For now, return a placeholder that will be updated in the auth layer\n return { valid: false, error: 'API key validation moved to auth layer' };\n}\n\n// Scope validation helper\nexport function hasScope(userScopes: ApiKeyScope[], requiredScope: ApiKeyScope): boolean {\n // Check for specific scope\n return userScopes.includes(requiredScope);\n}\n\n// Check if user has any of the required scopes\nexport function hasAnyScope(userScopes: ApiKeyScope[], requiredScopes: ApiKeyScope[]): boolean {\n return requiredScopes.some(scope => hasScope(userScopes, scope));\n}\n\n// Map scopes to Openship permissions\nexport function getPermissionsForScopes(scopes: ApiKeyScope[]): string[] {\n const permissions = new Set();\n \n scopes.forEach(scope => {\n switch (scope) {\n case 'read_orders':\n permissions.add('canReadOrders');\n break;\n case 'write_orders':\n permissions.add('canReadOrders');\n permissions.add('canManageOrders');\n permissions.add('canProcessOrders');\n break;\n case 'read_products':\n // Add product read permissions\n break;\n case 'write_products':\n // Add product write permissions\n break;\n case 'read_shops':\n permissions.add('canReadShops');\n break;\n case 'write_shops':\n permissions.add('canReadShops');\n permissions.add('canManageShops');\n permissions.add('canCreateShops');\n break;\n case 'read_channels':\n permissions.add('canReadChannels');\n break;\n case 'write_channels':\n permissions.add('canReadChannels');\n permissions.add('canManageChannels');\n permissions.add('canCreateChannels');\n break;\n case 'read_users':\n permissions.add('canReadUsers');\n break;\n case 'write_users':\n permissions.add('canReadUsers');\n permissions.add('canManageUsers');\n permissions.add('canManageRoles');\n break;\n }\n });\n \n return Array.from(permissions);\n}", "import { relationship, text } from \"@keystone-6/core/fields\";\nimport { list } from \"@keystone-6/core\";\nimport { isSignedIn, permissions } from \"../access\";\nimport { permissionFields } from \"./fields\";\n\nexport const Role = list({\n /*\n SPEC\n - [x] Block all public access\n - [x] Restrict edit access based on canManageRoles\n - [ ] Prevent users from deleting their own role\n - [ ] Add a pre-save hook that ensures some permissions are selected when others are:\n - [ ] when canEditOtherUsers is true, canSeeOtherUsers must be true\n - [ ] when canManageUsers is true, canEditOtherUsers and canSeeOtherUsers must be true\n - [ ] Extend the Admin UI with client-side validation based on the same set of rules\n */\n access: {\n operation: {\n query: isSignedIn,\n create: permissions.canManageRoles,\n update: permissions.canManageRoles,\n delete: permissions.canManageRoles,\n },\n },\n ui: {\n hideCreate: (args: any) => !permissions.canManageRoles({ session: args.session, context: args.context, listKey: 'Role', operation: 'create' }),\n hideDelete: (args: any) => !permissions.canManageRoles({ session: args.session, context: args.context, listKey: 'Role', operation: 'delete' }),\n listView: {\n initialColumns: [\"name\", \"assignedTo\"],\n },\n itemView: {\n defaultFieldMode: (args: any) =>\n permissions.canManageRoles({ session: args.session, context: args.context, listKey: 'Role', operation: 'update' }) ? \"edit\" : \"read\",\n },\n },\n fields: {\n /* The name of the role */\n name: text({ validation: { isRequired: true } }),\n ...permissionFields,\n assignedTo: relationship({\n ref: \"User.role\",\n many: true,\n ui: {\n itemView: { fieldMode: \"read\" },\n },\n }),\n },\n});", "import { checkbox } from '@keystone-6/core/fields';\n\nexport const permissionFields = {\n canSeeOtherUsers: checkbox({\n label: 'User can query other users',\n }),\n canEditOtherUsers: checkbox({\n label: 'User can edit other users',\n }),\n canManageUsers: checkbox({\n label: 'User can CRUD users',\n }),\n canManageRoles: checkbox({\n label: 'User can CRUD roles',\n }),\n canAccessDashboard: checkbox({\n label: 'User can access the dashboard',\n }),\n canSeeOtherShops: checkbox({\n label: 'User can query other shops',\n }),\n canManageShops: checkbox({\n label: 'User can CRUD shops',\n }),\n canCreateShops: checkbox({\n label: 'User can create shops',\n }),\n canSeeOtherChannels: checkbox({\n label: 'User can query other channels',\n }),\n canManageChannels: checkbox({\n label: 'User can CRUD channels',\n }),\n canCreateChannels: checkbox({\n label: 'User can create channels',\n }),\n canSeeOtherOrders: checkbox({\n label: 'User can query other orders',\n }),\n canManageOrders: checkbox({\n label: 'User can CRUD orders',\n }),\n canProcessOrders: checkbox({\n label: 'User can process orders',\n }),\n canSeeOtherMatches: checkbox({\n label: 'User can query other matches',\n }),\n canManageMatches: checkbox({\n label: 'User can CRUD matches',\n }),\n canCreateMatches: checkbox({\n label: 'User can create matches',\n }),\n canSeeOtherLinks: checkbox({\n label: 'User can query other links',\n }),\n canManageLinks: checkbox({\n label: 'User can CRUD links',\n }),\n canCreateLinks: checkbox({\n label: 'User can create links',\n }),\n canManagePlatforms: checkbox({\n label: 'User can manage platforms',\n }),\n canViewPlatformMetrics: checkbox({\n label: 'User can view platform metrics',\n }),\n canManageApiKeys: checkbox({\n label: 'User can manage API keys',\n }),\n canCreateApiKeys: checkbox({\n label: 'User can create API keys',\n }),\n canAccessAnalytics: checkbox({\n label: 'User can access analytics',\n }),\n canExportData: checkbox({\n label: 'User can export data',\n }),\n canManageWebhooks: checkbox({\n label: 'User can manage webhooks',\n }),\n};\n\n// export type Permission = keyof typeof permissionFields;\n\nexport const permissionsList = Object.keys(\n permissionFields\n);", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport {\n checkbox,\n float,\n integer,\n json,\n relationship,\n text,\n timestamp,\n} from \"@keystone-6/core/fields\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { placeMultipleOrders } from \"../lib/placeMultipleOrders\";\nimport { getMatches } from \"../extendGraphqlSchema/mutations/addMatchToCart\";\n\nasync function applyDynamicWhereClause(context: any, linkId: string, orderId: string) {\n const link = await context.query.Link.findOne({\n where: { id: linkId },\n query: 'id dynamicWhereClause',\n });\n\n if (!link || !link.dynamicWhereClause) {\n return null;\n }\n\n const whereClause = {\n ...link.dynamicWhereClause,\n id: { equals: orderId },\n };\n\n const matchedOrder = await context.query.Order.findOne({\n where: whereClause,\n query: 'id',\n });\n\n return matchedOrder;\n}\n\nexport const Order = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageOrders,\n },\n filter: {\n query: rules.canReadOrders,\n update: rules.canManageOrders,\n delete: rules.canManageOrders,\n },\n },\n hooks: {\n resolveInput: {\n create: ({ operation, resolvedData, context }) => {\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n return {\n ...resolvedData,\n user: { connect: { id: context.session.itemId } },\n };\n }\n return resolvedData;\n },\n },\n afterOperation: async ({ operation, item, context }: any) => {\n if (operation === \"create\") {\n const sudoContext = context.sudo();\n\n const order = await sudoContext.query.Order.findOne({\n where: { id: item.id },\n query: `\n id\n user {\n id\n }\n shop {\n id\n name\n linkMode\n links {\n id\n rank\n channel {\n id\n name\n }\n }\n }\n lineItems {\n name\n price\n lineItemId\n quantity\n image\n productId\n variantId\n sku\n }\n cartItemsCount\n `,\n });\n\n if (item.linkOrder && order.shop?.links.length > 0) {\n const links = order.shop.links.sort((a: any, b: any) => a.rank - b.rank);\n let matchedLinks: any[] = [];\n\n if (order.shop.linkMode === 'sequential') {\n for (const link of links) {\n const matchedOrder = await applyDynamicWhereClause(sudoContext, link.id, order.id);\n if (matchedOrder) {\n matchedLinks.push(link);\n break;\n }\n }\n } else if (order.shop.linkMode === 'simultaneous') {\n for (const link of links) {\n const matchedOrder = await applyDynamicWhereClause(sudoContext, link.id, order.id);\n if (matchedOrder) {\n matchedLinks.push(link);\n }\n }\n }\n\n if (matchedLinks.length > 0) {\n for (const link of matchedLinks) {\n await sudoContext.query.CartItem.createMany({\n data: order.lineItems.map((c: any) => ({\n ...c,\n channel: { connect: { id: link.channel.id } },\n order: { connect: { id: item.id } },\n user: { connect: { id: order.user?.id } },\n })),\n });\n }\n\n if (item.processOrder) {\n await placeMultipleOrders({\n ids: [item.id],\n query: sudoContext.query,\n });\n }\n } else {\n await sudoContext.query.Order.updateOne({\n where: { id: item.id },\n data: {\n error: \"No matching link found for this order\",\n },\n });\n }\n } else if (item.matchOrder) {\n if (item.matchOrder) {\n try {\n const cartItemsFromMatch = await getMatches({\n orderId: item.id,\n context: sudoContext,\n });\n\n const order = await sudoContext.query.Order.findOne({\n where: { id: item.id },\n query: `id error`,\n });\n if (order?.error) {\n const updatedOrder = await sudoContext.query.Order.updateOne({\n where: { id: item.id },\n data: {\n status: \"PENDING\",\n },\n });\n } else {\n if (item.processOrder) {\n const processedOrder = await placeMultipleOrders({\n ids: [item.id],\n query: sudoContext.query,\n });\n }\n }\n } catch (matchError) {\n // Handle match errors gracefully - don't break order creation\n console.error('Error during match processing:', matchError);\n await sudoContext.query.Order.updateOne({\n where: { id: item.id },\n data: {\n error: `Match processing failed: ${matchError instanceof Error ? matchError.message : 'Unknown error'}`,\n status: \"PENDING\",\n },\n });\n }\n }\n } else if (order.cartItemsCount > 0 && item.processOrder) {\n // Process the order if there are cart items and processOrder is true\n const processedOrder = await placeMultipleOrders({\n ids: [item.id],\n query: sudoContext.query,\n });\n }\n }\n },\n },\n ui: {\n listView: {\n initialColumns: [\"orderId\", \"orderName\", \"email\", \"totalPrice\", \"shop\"],\n },\n },\n fields: {\n // Order identifiers\n orderId: text({\n isIndexed: \"unique\",\n validation: { isRequired: true },\n }),\n orderName: text(),\n email: text(),\n\n // Customer information\n firstName: text(),\n lastName: text(),\n streetAddress1: text(),\n streetAddress2: text(),\n city: text(),\n state: text(),\n zip: text(),\n country: text(),\n phone: text(),\n\n // Pricing\n currency: text(),\n totalPrice: float(),\n subTotalPrice: float(),\n totalDiscounts: float(),\n totalTax: float(),\n\n // Processing flags\n linkOrder: checkbox({ defaultValue: true }),\n matchOrder: checkbox({ defaultValue: true }),\n processOrder: checkbox({ defaultValue: true }),\n\n // Status tracking\n status: text({ defaultValue: \"PENDING\" }),\n error: text({\n ui: {\n displayMode: \"textarea\",\n },\n }),\n\n // Metadata\n orderMetadata: json(),\n\n // Relationships\n shop: relationship({\n ref: \"Shop.orders\",\n ui: {\n displayMode: \"cards\",\n cardFields: [\"name\", \"domain\"],\n inlineCreate: { fields: [\"name\", \"domain\"] },\n inlineEdit: { fields: [\"name\", \"domain\"] },\n },\n }),\n lineItems: relationship({\n ref: \"LineItem.order\",\n many: true,\n ui: {\n displayMode: \"cards\",\n cardFields: [\"name\", \"quantity\", \"price\"],\n inlineCreate: { fields: [\"name\", \"quantity\", \"price\"] },\n inlineEdit: { fields: [\"name\", \"quantity\", \"price\"] },\n },\n }),\n cartItems: relationship({\n ref: \"CartItem.order\",\n many: true,\n }),\n user: relationship({\n ref: \"User.orders\",\n }),\n\n ...trackingFields,\n },\n});\n", "interface Platform {\n [key: string]: any;\n searchProductsFunction: string;\n getProductFunction: string;\n createPurchaseFunction: string;\n createWebhookFunction: string;\n deleteWebhookFunction: string;\n getWebhooksFunction: string;\n oAuthFunction: string;\n oAuthCallbackFunction: string;\n createTrackingWebhookHandler: string;\n cancelPurchaseWebhookHandler: string;\n}\n\nexport async function executeChannelAdapterFunction({\n platform,\n functionName,\n args,\n}: {\n platform: Platform;\n functionName: string;\n args: any;\n}) {\n const functionPath = platform[functionName];\n\n if (functionPath.startsWith('http')) {\n const response = await fetch(functionPath, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ platform, ...args }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP request failed: ${response.statusText}`);\n }\n return response.json();\n }\n\n const adapter = await import(\n `../../integrations/channel/${functionPath}.ts`\n );\n\n const fn = adapter[functionName];\n if (!fn) {\n throw new Error(\n `Function ${functionName} not found in adapter ${functionPath}`,\n );\n }\n\n try {\n return await fn({ platform, ...args });\n } catch (error: any) {\n throw new Error(\n `Error executing ${functionName} for platform ${functionPath}: ${error.message}`,\n );\n }\n}\n\n// Helper functions for common channel operations\nexport async function searchChannelProducts({\n platform,\n searchEntry,\n after,\n}: {\n platform: Platform;\n searchEntry: string;\n after?: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'searchProductsFunction',\n args: { searchEntry, after },\n });\n}\n\nexport async function getChannelProduct({\n platform,\n productId,\n variantId,\n}: {\n platform: Platform;\n productId: string;\n variantId?: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'getProductFunction',\n args: { productId, variantId },\n });\n}\n\nexport async function createChannelPurchase({\n platform,\n cartItems,\n shipping,\n notes,\n}: {\n platform: Platform;\n cartItems: any[];\n shipping: any;\n notes: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'createPurchaseFunction',\n args: { cartItems, shipping, notes },\n });\n}\n\nexport async function createChannelWebhook({\n platform,\n endpoint,\n events,\n}: {\n platform: Platform;\n endpoint: string;\n events: any[];\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'createWebhookFunction',\n args: { endpoint, events },\n });\n}\n\nexport async function deleteChannelWebhook({\n platform,\n webhookId,\n}: {\n platform: Platform;\n webhookId: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'deleteWebhookFunction',\n args: { webhookId },\n });\n}\n\nexport async function getChannelWebhooks({ platform }: { platform: Platform }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'getWebhooksFunction',\n args: {},\n });\n}\n\nexport async function handleChannelOAuth({\n platform,\n callbackUrl,\n}: {\n platform: Platform;\n callbackUrl: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'oAuthFunction',\n args: { callbackUrl },\n });\n}\n\nexport async function handleChannelOAuthCallback({\n platform,\n code,\n shop,\n state,\n}: {\n platform: Platform;\n code: string;\n shop: string;\n state: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'oAuthCallbackFunction',\n args: { code, shop, state },\n });\n}\n\nexport async function handleChannelTrackingWebhook({\n platform,\n event,\n headers,\n}: {\n platform: Platform;\n event: any;\n headers: any;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'createTrackingWebhookHandler',\n args: { event, headers },\n });\n}\n\nexport async function handleChannelCancelWebhook({\n platform,\n event,\n headers,\n}: {\n platform: Platform;\n event: any;\n headers: any;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'cancelPurchaseWebhookHandler',\n args: { event, headers },\n });\n}", "export async function executeShopAdapterFunction({ platform, functionName, args }: any) {\n const functionPath = platform[functionName];\n\n if (functionPath.startsWith(\"http\")) {\n const response = await fetch(functionPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform, ...args }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP request failed: ${response.statusText}`);\n }\n \n const result = await response.json();\n return result;\n }\n\n const adapter = await import(\n `../../integrations/shop/${functionPath}.ts`\n );\n\n const fn = adapter[functionName];\n if (!fn) {\n throw new Error(\n `Function ${functionName} not found in adapter ${functionPath}`\n );\n }\n\n try {\n const result = await fn({ platform, ...args });\n return result;\n } catch (error) {\n throw new Error(\n `Error executing ${functionName} for platform ${functionPath}: ${(error as any)?.message || 'Unknown error'}`\n );\n }\n}\n\n// Helper functions for common shop operations\nexport async function searchShopProducts({ platform, searchEntry, after }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"searchProductsFunction\",\n args: { searchEntry, after },\n });\n}\n\nexport async function getShopProduct({ platform, productId, variantId }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"getProductFunction\",\n args: { productId, variantId },\n });\n}\n\nexport async function searchShopOrders({ platform, searchEntry, after }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"searchOrdersFunction\",\n args: { searchEntry, after },\n });\n}\n\nexport async function updateShopProduct({ platform, productId, variantId, inventory, price }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"updateProductFunction\",\n args: { productId, variantId, inventory, price },\n });\n}\n\nexport async function addCartToPlatformOrder({ platform, cartItems, orderId }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"addCartToPlatformOrderFunction\",\n args: { cartItems, orderId },\n });\n}\n\nexport async function createShopWebhook({ platform, endpoint, events }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"createWebhookFunction\",\n args: { endpoint, events },\n });\n}\n\nexport async function deleteShopWebhook({ platform, webhookId }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"deleteWebhookFunction\",\n args: { webhookId },\n });\n}\n\nexport async function getShopWebhooks({ platform }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"getWebhooksFunction\",\n args: {},\n });\n}\n\nexport async function handleShopOAuth({ platform, callbackUrl }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"oAuthFunction\",\n args: { callbackUrl },\n });\n}\n\nexport async function handleShopOAuthCallback({ platform, code, shop, state }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"oAuthCallbackFunction\",\n args: { code, shop, state },\n });\n}\n\nexport async function handleShopOrderWebhook({ platform, event, headers }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"createOrderWebhookHandler\",\n args: { event, headers },\n });\n}\n\nexport async function handleShopCancelWebhook({ platform, event, headers }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"cancelOrderWebhookHandler\",\n args: { event, headers },\n });\n}", "import { createChannelPurchase } from \"../utils/channelProviderAdapter\";\nimport { addCartToPlatformOrder } from \"../utils/shopProviderAdapter\";\n\nasync function updateCartItems({\n query,\n cartItems,\n url = \"\",\n error = \"\",\n purchaseId = \"\",\n}: {\n query: any;\n cartItems: Array<{ id: string }>;\n url?: string;\n error?: string;\n purchaseId?: string;\n}) {\n const update = [];\n for (const { id } of cartItems) {\n const res = await query.CartItem.updateOne({\n where: {\n id,\n },\n data: {\n url,\n error,\n purchaseId,\n },\n });\n update.push(res);\n }\n return update;\n}\n\nexport async function placeMultipleOrders({ ids, query }: { ids: string[]; query: any }) {\n const processed = [];\n for (const orderId of ids) {\n const {\n firstName,\n lastName,\n streetAddress1,\n streetAddress2,\n city,\n state,\n zip,\n country,\n phone,\n user,\n shop,\n orderId: shopOrderId,\n orderName,\n } = await query.Order.findOne({\n where: {\n id: orderId,\n },\n query: `\n firstName,\n lastName,\n streetAddress1,\n streetAddress2,\n city,\n state,\n zip,\n country,\n phone\n shop {\n domain\n accessToken\n platform {\n addCartToPlatformOrderFunction\n }\n }\n orderId\n orderName\n user {\n email\n }\n `,\n });\n\n const cartChannels = await query.Channel.findMany({\n query: `\n domain\n accessToken\n cartItems(\n where: {\n order: { id: { equals: \"${orderId}\" }}\n purchaseId: { equals: \"\" }\n url: { equals: \"\" }\n }\n ) {\n id\n productId\n variantId\n sku\n name\n quantity\n price\n } \n platform {\n createPurchaseFunction\n }\n metadata\n `,\n });\n\n for (const {\n domain,\n accessToken,\n cartItems,\n platform,\n metadata,\n } of cartChannels.filter((channel: any) => channel.cartItems.length > 0)) {\n const body = {\n domain,\n accessToken,\n cartItems,\n address: {\n firstName,\n lastName,\n streetAddress1,\n streetAddress2,\n city,\n state,\n zip,\n country,\n phone,\n },\n email: user.email,\n orderName,\n orderId,\n shopOrderId,\n metadata,\n };\n\n // Prepare platform configuration like other functions do\n const platformConfig = {\n domain,\n accessToken,\n createPurchaseFunction: platform.createPurchaseFunction,\n ...metadata,\n };\n\n try {\n const orderPlacementRes = await createChannelPurchase({\n platform: platformConfig,\n cartItems,\n shipping: {\n firstName,\n lastName,\n address1: streetAddress1,\n address2: streetAddress2,\n city,\n province: state,\n zip,\n country,\n phone,\n email: user.email,\n },\n notes: \"\",\n });\n\n if (orderPlacementRes.error) {\n await updateCartItems({\n cartItems,\n error: `ORDER_PLACEMENT_ERROR: ${orderPlacementRes.error}`,\n query,\n });\n }\n\n if (orderPlacementRes.purchaseId) {\n await updateCartItems({\n cartItems,\n url: orderPlacementRes.url,\n purchaseId: orderPlacementRes.purchaseId,\n query,\n });\n }\n } catch (error: any) {\n await updateCartItems({\n cartItems,\n error: `ORDER_PLACEMENT_ERROR: ${error.message || \"Error on order placement. Order may have been placed.\"}`,\n query,\n });\n }\n\n const cartCount = await query.CartItem.count({\n where: {\n order: {\n id: { equals: orderId },\n },\n url: { equals: \"\" },\n purchaseId: { equals: \"\" },\n },\n });\n\n if (cartCount === 0) {\n const updatedOrder = await query.Order.updateOne({\n where: { id: orderId },\n data: {\n status: \"AWAITING\",\n },\n query: `\n id\n orderId\n cartItems {\n id,\n name,\n quantity,\n price,\n image,\n productId,\n variantId,\n sku,\n purchaseId,\n lineItemId,\n channel {\n id\n name\n },\n url,\n error,\n }\n shop {\n platform {\n addCartToPlatformOrderFunction\n }\n }\n `,\n });\n\n try {\n await addCartToPlatformOrder({\n platform: updatedOrder.shop.platform,\n cartItems: updatedOrder.cartItems,\n orderId: updatedOrder.orderId,\n });\n } catch (error: any) {\n console.warn(\n \"Warning: Add cart to platform order function failed:\",\n error.message\n );\n }\n\n processed.push(updatedOrder);\n } else {\n const updatedOrder = await query.Order.updateOne({\n where: { id: orderId },\n data: {\n status: \"PENDING\",\n },\n query: `\n orderId\n cartItems {\n channel {\n id\n }\n image\n price\n id\n quantity\n productId\n variantId\n sku\n }\n `,\n });\n\n processed.push(updatedOrder);\n }\n }\n }\n return processed;\n}", "import type { KeystoneContext } from '@keystone-6/core/types';\nimport { executeChannelAdapterFunction } from '../../../integrations/channel/lib/executor';\n\ninterface AddMatchToCartArgs {\n orderId: string;\n}\n\nexport async function getMatches({ orderId, context }: { orderId: string; context: KeystoneContext }) {\n async function createCartItems({ matches }: { matches: any[] }) {\n if (matches.length > 0) {\n let result;\n for (const existingMatch of matches) {\n for (const {\n channel,\n productId,\n variantId,\n price: matchPrice,\n id,\n user,\n ...rest\n } of existingMatch.output) {\n // Create platform object with all necessary data\n const platformData = {\n ...channel.platform,\n domain: channel.domain,\n accessToken: channel.accessToken,\n };\n\n // Use the new executor pattern to get product data\n const productResult = await executeChannelAdapterFunction({\n platform: platformData,\n functionName: \"getProductFunction\",\n args: { productId, variantId },\n });\n \n const product = productResult.product;\n\n // Simple string comparison - no parsing needed\n const currentPriceStr = String(product.price || '');\n const savedPriceStr = String(matchPrice || '');\n const hasPriceChange = currentPriceStr !== savedPriceStr;\n \n // Store price as text (no parsing needed)\n const priceValue = currentPriceStr;\n\n result = await context.query.CartItem.createOne({\n data: {\n price: priceValue,\n productId,\n variantId,\n image: product.image,\n name: product.title,\n order: { connect: { id: order.id } },\n channel: { connect: { id: channel.id } },\n ...(hasPriceChange && {\n error: `PRICE_CHANGE: Price changed: ${savedPriceStr} \u2192 ${currentPriceStr}. Verify before placing order.`,\n }),\n user: { connect: { id: user.id } },\n ...rest,\n },\n });\n }\n }\n\n return result;\n }\n }\n\n const order = await context.query.Order.findOne({\n where: {\n id: orderId,\n },\n query: `\n id\n user {\n id\n } \n lineItems {\n image\n price\n id\n quantity\n productId\n variantId\n lineItemId\n }`,\n });\n\n if (!order) {\n throw new Error(\"Order not found\");\n }\n\n const allMatches = await context.query.Match.findMany({\n where: {\n user: {\n id: { equals: order.user.id },\n },\n AND: order.lineItems.map(({ productId, variantId, quantity }: any) => ({\n input: {\n some: {\n productId: { equals: productId },\n variantId: { equals: variantId },\n quantity: { equals: quantity },\n },\n },\n })),\n },\n query: ` \n inputCount\n outputCount\n input {\n id\n quantity\n productId\n variantId\n shop {\n id\n }\n user {\n id\n }\n }\n output {\n id\n quantity\n productId\n variantId\n price\n channel {\n id\n domain\n accessToken\n platform {\n id\n getProductFunction\n }\n }\n user {\n id\n }\n }\n `,\n });\n\n const [filt] = allMatches.filter(\n ({ inputCount }) => inputCount === order.lineItems.length\n );\n\n if (filt) {\n return await createCartItems({ matches: [filt] });\n } else {\n if (order.lineItems.length > 1) {\n const output = await Promise.all(\n order.lineItems.map(async ({ quantity, variantId, productId }: any) => {\n const singleAllMatches = await context.query.Match.findMany({\n where: {\n user: {\n id: { equals: order.user.id },\n },\n AND: [\n {\n input: {\n every: {\n productId: { equals: productId },\n variantId: { equals: variantId },\n quantity: { equals: quantity },\n },\n },\n },\n ],\n },\n query: `\n input {\n id\n quantity\n productId\n variantId\n shop {\n id\n }\n }\n output {\n id\n quantity\n productId\n variantId\n price\n channel {\n id\n domain\n accessToken\n platform {\n id\n getProductFunction\n }\n }\n user {\n id\n }\n }\n `,\n });\n\n const [singleFilt] = singleAllMatches;\n\n if (singleFilt) {\n return singleFilt;\n }\n await context.query.Order.updateOne({\n where: { id: orderId },\n data: {\n error: \"MATCH_ERROR: Some lineItems not matched\",\n status: \"PENDING\",\n },\n });\n })\n );\n\n if (output.filter((value) => value !== undefined).length) {\n return await createCartItems({ matches: output });\n }\n } else {\n await context.query.Order.updateOne({\n where: { id: orderId },\n data: {\n error: \"MATCH_ERROR: No matches found\",\n },\n });\n }\n }\n}\n\nasync function addMatchToCart(\n root: any,\n { orderId }: AddMatchToCartArgs,\n context: KeystoneContext\n) {\n const session = context.session;\n if (!session?.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n const cartItemsFromMatch = await getMatches({\n orderId,\n context,\n });\n\n if (cartItemsFromMatch) {\n return await context.db.Order.findOne({\n where: { id: orderId },\n });\n } else {\n throw new Error(\"No Matches found\");\n }\n}\n\nexport default addMatchToCart;", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport { relationship, text, timestamp } from \"@keystone-6/core/fields\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const TrackingDetail = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageOrders,\n },\n filter: {\n query: rules.canReadOrders,\n update: rules.canManageOrders,\n delete: rules.canManageOrders,\n },\n },\n hooks: {\n resolveInput: {\n create: ({ operation, resolvedData, context }) => {\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n return {\n ...resolvedData,\n user: { connect: { id: context.session.itemId } },\n };\n }\n return resolvedData;\n },\n },\n afterOperation: async ({ operation, item, context }) => {\n if (operation === \"create\") {\n const sudoContext = context.sudo();\n \n // Get tracking detail with related data\n const foundTracking = await sudoContext.query.TrackingDetail.findOne({\n where: { id: String(item.id) },\n query: `\n id\n trackingNumber\n trackingCompany\n purchaseId\n cartItems {\n id\n purchaseId\n order {\n id\n orderName\n orderId\n status\n shop {\n id\n domain\n accessToken\n platform {\n id\n name\n addTrackingFunction\n }\n }\n }\n }\n `,\n });\n \n if (!foundTracking?.cartItems?.length) {\n return;\n }\n \n const firstCartItem = foundTracking.cartItems[0];\n const order = firstCartItem.order;\n \n // Execute shop platform addTracking function\n if (order.shop?.platform?.addTrackingFunction) {\n try {\n // Use the executor pattern\n const { addShopTracking } = await import('../../integrations/shop/lib/executor');\n \n await addShopTracking({\n platform: {\n ...order.shop.platform,\n domain: order.shop.domain,\n accessToken: order.shop.accessToken,\n },\n order: order,\n trackingCompany: foundTracking.trackingCompany,\n trackingNumber: foundTracking.trackingNumber,\n });\n } catch (error) {\n console.error('Error calling addTracking:', error);\n // Don't throw - continue with order status update even if shop tracking fails\n }\n }\n \n // Check if all cart items for this order have tracking\n const foundOrder = await sudoContext.query.Order.findOne({\n where: { id: order.id },\n query: `\n id\n orderName\n status\n cartItems(\n where: {\n AND: [\n { trackingDetails: { none: {} } },\n { status: { not: { equals: \"CANCELLED\" } } }\n ]\n }\n ) {\n id\n status\n }\n `,\n });\n \n // If no untracked items remain, update order status to COMPLETE\n if (foundOrder && foundOrder.cartItems.length === 0 && foundOrder.status === \"AWAITING\") {\n await sudoContext.query.Order.updateOne({\n where: { id: foundOrder.id },\n data: {\n status: \"COMPLETE\",\n },\n });\n }\n }\n },\n },\n ui: {\n listView: {\n initialColumns: [\"trackingCompany\", \"trackingNumber\", \"purchaseId\"],\n },\n },\n fields: {\n // Tracking information\n trackingCompany: text({\n validation: { isRequired: true },\n }),\n trackingNumber: text({\n validation: { isRequired: true },\n }),\n purchaseId: text(),\n\n // Relationships\n cartItems: relationship({\n ref: \"CartItem.trackingDetails\",\n many: true,\n ui: {\n displayMode: \"cards\",\n cardFields: [\"name\", \"quantity\", \"status\"],\n },\n }),\n user: relationship({\n ref: \"User.trackingDetails\",\n }),\n\n ...trackingFields,\n },\n});\n", "import { list } from '@keystone-6/core'\nimport { allOperations } from '@keystone-6/core/access'\nimport { float, integer, relationship, text, timestamp } from '@keystone-6/core/fields'\n\nimport { isSignedIn, permissions, rules } from '../access'\nimport { trackingFields } from \"./trackingFields\";\n\nexport const LineItem = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageOrders,\n },\n filter: {\n query: rules.canReadOrders,\n update: rules.canManageOrders,\n delete: rules.canManageOrders,\n },\n },\n hooks: {\n resolveInput: {\n create: ({ operation, resolvedData, context }) => {\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n return {\n ...resolvedData,\n user: { connect: { id: context.session.itemId } },\n }\n }\n return resolvedData\n },\n },\n },\n ui: {\n listView: {\n initialColumns: ['name', 'quantity', 'price', 'order'],\n },\n },\n fields: {\n // Product information\n name: text({\n validation: { isRequired: true },\n }),\n image: text(),\n price: float(),\n quantity: integer(),\n \n // Product identifiers\n productId: text(),\n variantId: text(),\n sku: text(),\n lineItemId: text(),\n \n // Relationships\n order: relationship({\n ref: 'Order.lineItems',\n ui: {\n displayMode: 'cards',\n cardFields: ['orderId', 'orderName'],\n },\n }),\n user: relationship({\n ref: 'User.lineItems',\n }),\n \n ...trackingFields\n },\n})", "import { list } from '@keystone-6/core'\nimport { allOperations } from '@keystone-6/core/access'\nimport { float, integer, relationship, text, timestamp } from '@keystone-6/core/fields'\n\nimport { isSignedIn, permissions, rules } from '../access'\nimport { trackingFields } from './trackingFields'\n\nexport const CartItem = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageOrders,\n },\n filter: {\n query: rules.canReadOrders,\n update: rules.canManageOrders,\n delete: rules.canManageOrders,\n },\n },\n hooks: {\n resolveInput: {\n create: ({ operation, resolvedData, context }) => {\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n return {\n ...resolvedData,\n user: { connect: { id: context.session.itemId } },\n }\n }\n return resolvedData\n },\n },\n },\n ui: {\n listView: {\n initialColumns: ['name', 'quantity', 'price', 'status', 'channel'],\n },\n },\n fields: {\n // Product information\n name: text({\n validation: { isRequired: true },\n }),\n image: text(),\n price: text(),\n quantity: integer(),\n \n // Product identifiers\n productId: text(),\n variantId: text(),\n sku: text(),\n lineItemId: text(),\n \n // Processing information\n url: text(),\n error: text({\n ui: {\n displayMode: 'textarea',\n },\n }),\n purchaseId: text(),\n status: text({ defaultValue: 'PENDING' }),\n \n // Relationships\n order: relationship({\n ref: 'Order.cartItems',\n ui: {\n displayMode: 'cards',\n cardFields: ['orderId', 'orderName'],\n },\n }),\n channel: relationship({\n ref: 'Channel.cartItems',\n ui: {\n displayMode: 'cards',\n cardFields: ['name', 'domain'],\n },\n }),\n trackingDetails: relationship({\n ref: 'TrackingDetail.cartItems',\n many: true,\n }),\n user: relationship({\n ref: 'User.cartItems',\n }),\n \n ...trackingFields\n },\n})", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport { json, relationship, text, timestamp, virtual } from \"@keystone-6/core/fields\";\nimport { graphql } from \"@keystone-6/core\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { getBaseUrl } from '../../dashboard/lib/getBaseUrl';\nimport { executeChannelAdapterFunction } from '../utils/channelProviderAdapter';\n\nexport const Channel = list({\n access: {\n operation: {\n query: permissions.canSeeOtherChannels,\n create: permissions.canCreateChannels,\n update: permissions.canManageChannels,\n delete: permissions.canManageChannels,\n },\n filter: {\n query: rules.canReadChannels,\n update: rules.canManageChannels,\n delete: rules.canManageChannels,\n },\n },\n ui: {\n listView: {\n initialColumns: [\"name\", \"domain\", \"platform\"],\n },\n },\n fields: {\n name: text({\n validation: { isRequired: true },\n }),\n domain: text(),\n accessToken: text({\n ui: {\n displayMode: \"textarea\",\n },\n }),\n refreshToken: text({\n ui: {\n displayMode: \"textarea\",\n description: \"Long-lived OAuth refresh token (30 days)\",\n },\n }),\n tokenExpiresAt: timestamp({\n ui: {\n description: \"When the current access token expires\",\n },\n }),\n metadata: json({\n defaultValue: {},\n }),\n\n // Relationships\n platform: relationship({\n ref: \"ChannelPlatform.channels\",\n }),\n user: relationship({\n ref: \"User.channels\",\n hooks: {\n resolveInput: ({ operation, resolvedData, context }) => {\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n links: relationship({\n ref: \"Link.channel\",\n many: true,\n }),\n channelItems: relationship({\n ref: \"ChannelItem.channel\",\n many: true,\n }),\n cartItems: relationship({\n ref: \"CartItem.channel\",\n many: true,\n }),\n\n // Virtual field for webhooks with proper base URL\n webhooks: virtual({\n field: graphql.field({\n type: graphql.JSON,\n async resolve(item: any, args: any, context: any): Promise {\n try {\n const recommendedWebhooks = [\n {\n callbackUrl: `/api/handlers/channel/cancel-purchase/${item.id}`,\n topic: \"ORDER_CANCELLED\",\n description: \"When a purchase order is cancelled by this channel, enabling this will notify Openship to mark the cart item as cancelled and move the order to PENDING for reprocessing.\",\n },\n {\n callbackUrl: `/api/handlers/channel/create-tracking/${item.id}`,\n topic: \"TRACKING_CREATED\",\n description: \"When a purchase order is fulfilled by this channel, enabling this will notify Openship to add the tracking to the order and shop.\",\n },\n ];\n\n // Get platform data with relationships resolved\n const channelWithPlatform = await context.query.Channel.findOne({\n where: { id: String(item.id) },\n query: 'platform { getWebhooksFunction }'\n });\n\n if (!channelWithPlatform?.platform?.getWebhooksFunction) {\n return {\n success: false,\n error: \"Get webhooks function not configured\",\n recommendedWebhooks\n } as any;\n }\n\n const platformConfig: any = {\n domain: item.domain,\n accessToken: item.accessToken,\n getWebhooksFunction: channelWithPlatform.platform.getWebhooksFunction,\n ...(item.metadata || {}),\n };\n\n const webhooksResult = await executeChannelAdapterFunction({\n platform: platformConfig,\n functionName: 'getWebhooksFunction',\n args: {},\n });\n\n return {\n success: true,\n data: { webhooks: webhooksResult.webhooks || [] },\n recommendedWebhooks\n } as any;\n } catch (error) {\n console.error('Error in webhooks virtual field:', error);\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n recommendedWebhooks: [\n {\n callbackUrl: `/api/handlers/channel/cancel-purchase/${item.id}`,\n topic: \"ORDER_CANCELLED\",\n description: \"When a purchase order is cancelled by this channel, enabling this will notify Openship to mark the cart item as cancelled and move the order to PENDING for reprocessing.\",\n },\n {\n callbackUrl: `/api/handlers/channel/create-tracking/${item.id}`,\n topic: \"TRACKING_CREATED\",\n description: \"When a purchase order is fulfilled by this channel, enabling this will notify Openship to add the tracking to the order and shop.\",\n },\n ]\n } as any;\n }\n },\n }),\n }),\n\n ...trackingFields,\n },\n});\n", "import {\n integer,\n text,\n relationship,\n virtual,\n float,\n} from \"@keystone-6/core/fields\";\nimport { graphql, list } from \"@keystone-6/core\";\nimport { isSignedIn, rules, permissions } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { getChannelProduct } from \"../extendGraphqlSchema/queries\";\n\nfunction mergeData(existingData: any, newData: any) {\n const updatedData = {};\n\n // Loop through all keys in existingData to create a base for updatedData\n Object.keys(existingData).forEach((key) => {\n // Default to existing data\n (updatedData as any)[key] = existingData[key];\n\n // Check if new data is provided for the key\n if (newData[key] !== undefined) {\n if (typeof newData[key] === \"object\" && newData[key] !== null) {\n // Handle connect and disconnect for relationships\n if (newData[key].connect) {\n (updatedData as any)[key] = newData[key].connect.id; // Use connected ID\n } else if (newData[key].disconnect) {\n (updatedData as any)[key] = null; // Disconnect the relationship\n }\n } else {\n // Directly assign new data if it's not an object or null\n (updatedData as any)[key] = newData[key];\n }\n }\n });\n\n return updatedData;\n}\n\nexport const ChannelItem = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: isSignedIn,\n },\n filter: {\n query: rules.canReadMatches,\n update: rules.canUpdateMatches,\n delete: rules.canUpdateMatches,\n },\n },\n fields: {\n quantity: integer(),\n productId: text(),\n variantId: text(),\n lineItemId: text(),\n price: text(),\n priceChanged: virtual({\n field: graphql.field({\n type: graphql.String,\n async resolve(item: any, args: any, context: any) {\n const channelItem = await context.query.ChannelItem.findOne({\n where: { id: item.id },\n query: 'price externalDetails { price }',\n });\n \n if (channelItem && channelItem.price && channelItem.externalDetails?.price) {\n const savedPrice = channelItem.price;\n const currentPrice = channelItem.externalDetails.price;\n \n if (savedPrice !== currentPrice) {\n return `Price changed from ${savedPrice} to ${currentPrice}`;\n }\n }\n return null;\n },\n }),\n }),\n externalDetails: virtual({\n field: graphql.field({\n type: graphql.object()({\n name: \"ChannelProduct\",\n fields: {\n image: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.image }),\n title: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.title }),\n productId: graphql.field({ type: graphql.ID, resolve: (parent: any) => parent.productId }),\n variantId: graphql.field({ type: graphql.ID, resolve: (parent: any) => parent.variantId }),\n price: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.price }),\n availableForSale: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.availableForSale }),\n productLink: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.productLink }),\n inventory: graphql.field({ type: graphql.Int, resolve: (parent: any) => parent.inventory }),\n inventoryTracked: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.inventoryTracked }),\n error: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.error }),\n },\n }),\n resolve: async (item: any, args: any, context: any): Promise => {\n const channelItem = await context.query.ChannelItem.findOne({\n where: { id: item.id },\n query: \"channel { id }\",\n });\n\n if (!channelItem?.channel) {\n console.error(\"Channel not associated or missing.\");\n return { error: \"Channel not associated or missing.\" };\n }\n\n const channelId = String(channelItem.channel.id);\n\n try {\n const product = await getChannelProduct(\n null,\n {\n channelId: channelId,\n productId: item.productId,\n variantId: item.variantId,\n },\n context\n );\n return product;\n } catch (error) {\n console.error(\"Failed to fetch external details:\", error);\n return { error: \"Failed to fetch external details.\" };\n }\n },\n }),\n ui: {\n query:\n \"{ image title productId variantId price availableForSale productLink inventory inventoryTracked error }\",\n },\n }),\n matches: relationship({ ref: \"Match.output\", many: true }),\n channel: relationship({ ref: \"Channel.channelItems\" }),\n user: relationship({\n ref: \"User.channelItems\",\n hooks: {\n resolveInput({ operation, resolvedData, context }) {\n // Default to the currently logged in user on create.\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session?.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n ...trackingFields,\n },\n db: {\n extendPrismaSchema: (schema) => {\n // add a (poor) example of a multi-column unique constraint\n return schema.replace(\n /(model [^}]+)}/g,\n \"$1@@unique([quantity, productId, variantId, channelId, userId])\\n}\"\n );\n },\n },\n});", "import { searchChannelProducts } from \"../../utils/channelProviderAdapter\";\n\nasync function getMatches({ inputArray, user, context }: {\n inputArray: any[];\n user: { id: string };\n context: any;\n}) {\n const allMatches = await context.query.Match.findMany({\n where: {\n user: { id: { equals: user.id } },\n AND: inputArray.map(({ productId, variantId, quantity }) => ({\n input: {\n some: {\n productId,\n variantId,\n quantity,\n },\n },\n })),\n },\n query: ` \n id\n inputCount\n outputCount\n input {\n id\n quantity\n productId\n variantId\n shop {\n id\n }\n user {\n id\n }\n }\n output {\n id\n quantity\n productId\n variantId\n price\n channel {\n id\n domain\n accessToken\n name\n platform {\n id\n searchProductsFunction\n }\n }\n user {\n id\n }\n }\n `,\n });\n\n const [filt] = allMatches.filter(\n ({ inputCount }: any) => inputCount === inputArray.length\n );\n\n if (filt) {\n return [filt];\n }\n throw new Error(\"No match found\");\n}\n\nasync function getMatch(root: any, { input }: { input: any[] }, context: any) {\n const sesh = context.session;\n if (!sesh.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n const existingMatches = await getMatches({\n inputArray: input,\n user: { id: sesh.itemId },\n context,\n });\n\n const cleanEM = existingMatches.filter((a) => a !== undefined);\n\n if (cleanEM.length > 0) {\n const output = [];\n for (const existingMatch of cleanEM) {\n for (const {\n channel,\n productId,\n variantId,\n quantity,\n price: matchPrice,\n id,\n userId,\n channelId,\n ...rest\n } of existingMatch.output) {\n const { searchProductsFunction } = channel.platform;\n\n const searchResult = await searchChannelProducts({\n platform: channel.platform,\n searchEntry: productId,\n after: undefined,\n });\n \n const products = searchResult.products;\n\n const [productInfo] = products;\n productInfo.name = productInfo.title;\n output.push({ ...productInfo, channelName: channel.name, quantity });\n }\n }\n return output;\n }\n}\n\nexport default getMatch;", "async function getMatches({ inputArray, user, context }: {\n inputArray: any[];\n user: { id: string };\n context: any;\n}) {\n const allMatches = await context.query.Match.findMany({\n where: {\n user: { id: { equals: user.id } },\n AND: inputArray.map(({ productId, variantId, quantity }) => ({\n input: {\n some: {\n productId,\n variantId,\n quantity,\n },\n },\n })),\n },\n query: ` \n id\n inputCount\n `,\n });\n\n const filteredValues = allMatches.filter(\n ({ inputCount }: any) => inputCount === inputArray.length\n );\n\n // if (filteredValues.length) {\n // return allMatches.length;\n // } else {\n // return 0;\n // }\n return filteredValues.length;\n}\n\nasync function getMatchCount(root: any, { input }: { input: any[] }, context: any) {\n // 1. Query the current user see if they are signed in\n const sesh = context.session;\n if (!sesh.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n const existingMatchesCount = await getMatches({\n inputArray: input,\n user: { id: sesh.itemId },\n context,\n });\n\n return existingMatchesCount;\n}\n\nexport default getMatchCount;", "import { getShopWebhooks as executeGetShopWebhooks } from \"../../utils/shopProviderAdapter\";\n\ninterface GetShopWebhooksArgs {\n shopId: string;\n}\n\nasync function getShopWebhooks(\n root: any,\n { shopId }: GetShopWebhooksArgs,\n context: any\n) {\n try {\n // Fetch the shop using the provided shopId\n const shop = await context.query.Shop.findOne({\n where: { id: shopId },\n query: \"id domain accessToken platform { id getWebhooksFunction }\",\n });\n\n \n if (!shop) {\n throw new Error(\"Shop not found\");\n }\n\n if (!shop.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n const result = await executeGetShopWebhooks({\n platform: {\n ...shop.platform,\n domain: shop.domain,\n accessToken: shop.accessToken,\n },\n });\n\n return result.webhooks;\n } catch (error: any) {\n throw new Error(`Error getting shop webhooks: ${error.message}`);\n }\n}\n\nexport default getShopWebhooks;", "async function redirectToInit(root: any, { ids }: any, context: any) {\n // 1. Query the current user see if they are signed in\n const userCount = await context.sudo().query.User.count({});\n\n if (userCount === 0) {\n return true;\n }\n return false;\n}\n\nexport default redirectToInit;", "import type { KeystoneContext } from '@keystone-6/core/types';\nimport { searchShopOrders as searchShopOrdersExecutor } from \"../../utils/shopProviderAdapter\";\n\ninterface SearchShopOrdersArgs {\n shopId: string;\n searchEntry?: string;\n take: number;\n skip?: number;\n after?: string;\n status?: string;\n financialStatus?: string;\n fulfillmentStatus?: string;\n dateFrom?: string;\n dateTo?: string;\n}\n\nasync function searchShopOrders(\n root: any,\n { shopId, searchEntry, take = 25, skip = 0, after, status, financialStatus, fulfillmentStatus, dateFrom, dateTo }: SearchShopOrdersArgs,\n context: KeystoneContext\n) {\n // Validate input parameters\n if (!shopId || typeof shopId !== 'string') {\n throw new Error(\"Valid shop ID is required\");\n }\n\n if (take > 250) {\n throw new Error(\"Cannot fetch more than 250 orders at once\");\n }\n\n if (take < 1) {\n throw new Error(\"Take must be at least 1\");\n }\n // Fetch the shop using the provided shopId\n const shop = await context.query.Shop.findOne({\n where: { id: shopId },\n query: `\n id \n domain \n accessToken \n metadata\n platform { \n id \n name\n searchOrdersFunction \n appKey\n appSecret\n }\n `,\n });\n\n \n if (!shop) {\n throw new Error(\"Shop not found\");\n }\n\n if (!shop.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n if (!shop.platform.searchOrdersFunction) {\n throw new Error(\"Search orders function not configured.\");\n }\n\n // Prepare platform configuration with enhanced filtering\n const platformConfig = {\n domain: shop.domain,\n accessToken: shop.accessToken,\n ...shop.metadata,\n };\n\n // Build advanced filter options\n const filterOptions = {\n searchEntry,\n after,\n take,\n skip,\n // Advanced filtering capabilities\n filters: {\n status: status || undefined,\n financialStatus: financialStatus || undefined,\n fulfillmentStatus: fulfillmentStatus || undefined,\n createdAtMin: dateFrom ? new Date(dateFrom).toISOString() : undefined,\n createdAtMax: dateTo ? new Date(dateTo).toISOString() : undefined,\n },\n };\n\n try {\n const result = await searchShopOrdersExecutor({\n platform: {\n ...shop.platform,\n ...platformConfig,\n },\n ...filterOptions,\n });\n\n // Enhance the result with additional metadata\n return {\n orders: result.orders || [],\n pageInfo: {\n hasNextPage: result.pageInfo?.hasNextPage || false,\n hasPreviousPage: result.pageInfo?.hasPreviousPage || false,\n startCursor: result.pageInfo?.startCursor || null,\n endCursor: result.pageInfo?.endCursor || null,\n },\n totalCount: result.totalCount || null,\n shopInfo: {\n id: shop.id,\n domain: shop.domain,\n platformName: shop.platform.name,\n },\n searchMetadata: {\n searchEntry,\n filtersApplied: Object.keys(filterOptions.filters).filter(\n key => (filterOptions.filters as Record)[key] !== undefined\n ),\n fetchedAt: new Date().toISOString(),\n resultCount: result.orders?.length || 0,\n },\n };\n } catch (error) {\n console.error(`Error searching orders for shop ${shop.id}:`, error);\n throw new Error(`Failed to search orders from ${shop.platform.name}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n\nexport default searchShopOrders;", "\"use server\";\n\nimport { searchShopProducts } from \"../../utils/shopProviderAdapter\";\n\nasync function searchShopProductsQuery(\n root: any,\n { shopId, searchEntry, after }: { shopId: string; searchEntry: string; after?: string },\n context: any\n) {\n const sudoContext = context.sudo();\n\n // Fetch the shop using the provided shopId\n const shop = await sudoContext.query.Shop.findOne({\n where: { id: shopId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n name\n searchProductsFunction\n appKey\n appSecret\n }\n `,\n });\n\n if (!shop) {\n throw new Error(\"Shop not found\");\n }\n\n if (!shop.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n if (!shop.platform.searchProductsFunction) {\n throw new Error(\"Search products function not configured.\");\n }\n\n // Prepare platform configuration\n const platformConfig = {\n domain: shop.domain,\n accessToken: shop.accessToken,\n ...shop.metadata,\n };\n\n try {\n const result = await searchShopProducts({\n platform: {\n ...shop.platform,\n ...platformConfig,\n },\n searchEntry: searchEntry || \"\",\n after,\n });\n\n return result.products;\n } catch (error) {\n console.error(\"Error searching shop products:\", error);\n throw new Error(`Failed to search products: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n\nexport default searchShopProductsQuery;", "'use server';\n\nimport { searchChannelProducts } from '../../utils/channelProviderAdapter';\n\nasync function searchChannelProductsQuery(\n root: any,\n {\n channelId,\n searchEntry,\n after,\n }: { channelId: string; searchEntry: string; after?: string },\n context: any,\n) {\n console.log(\"helllooooo\")\n const sudoContext = context.sudo();\n\n // Fetch the channel using the provided channelId\n const channel = await sudoContext.query.Channel.findOne({\n where: { id: channelId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n name\n searchProductsFunction\n }\n `,\n });\n\n if (!channel) {\n throw new Error('Channel not found');\n }\n\n if (!channel.platform) {\n throw new Error('Platform configuration not specified.');\n }\n\n if (!channel.platform.searchProductsFunction) {\n throw new Error('Search products function not configured.');\n }\n\n // Prepare platform configuration\n const platformConfig = {\n domain: channel.domain,\n accessToken: channel.accessToken,\n searchProductsFunction: channel.platform.searchProductsFunction,\n ...channel.metadata,\n };\n\n try {\n const result = await searchChannelProducts({\n platform: platformConfig,\n searchEntry: searchEntry || '',\n after,\n });\n\n return result.products;\n } catch (error: any) {\n console.error('Error searching channel products:', error);\n throw new Error(`Failed to search products: ${error.message}`);\n }\n}\n\nexport default searchChannelProductsQuery;", "import { getChannelWebhooks as executeGetChannelWebhooks } from \"../../utils/channelProviderAdapter\";\n\ninterface GetChannelWebhooksArgs {\n channelId: string;\n}\n\nasync function getChannelWebhooks(\n root: any,\n { channelId }: GetChannelWebhooksArgs,\n context: any\n) {\n try {\n // Fetch the channel using the provided channelId\n const channel = await context.query.Channel.findOne({\n where: { id: channelId },\n query: \"id domain accessToken platform { id getWebhooksFunction }\",\n });\n\n if (!channel) {\n throw new Error(\"Channel not found\");\n }\n\n if (!channel.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n const result = await executeGetChannelWebhooks({\n platform: channel.platform,\n });\n\n return result.webhooks;\n } catch (error: any) {\n throw new Error(`Error getting channel webhooks: ${error.message}`);\n }\n}\n\nexport default getChannelWebhooks;", "async function getFilteredMatches(root: any, args: any, context: any) {\n // Fetch all matches\n const matches = await context.query.Match.findMany({\n query: `\n id \n outputPriceChanged\n inventoryNeedsToBeSynced { syncEligible sourceQuantity targetQuantity }\n input { \n id quantity productId variantId lineItemId \n externalDetails { title image price productLink inventory inventoryTracked } \n shop { id name } \n } \n output { \n id quantity productId variantId lineItemId \n externalDetails { title image price productLink inventory inventoryTracked } \n price channel { id name } \n }\n `,\n });\n\n // console.log(matches);\n // Filter matches based on inventoryNeedsToBeSynced.syncEligible\n const filteredMatches = matches.filter((match: any) => match.inventoryNeedsToBeSynced.syncEligible);\n\n // Return the filtered matches\n return filteredMatches;\n}\n\nexport default getFilteredMatches;", "import { getChannelProduct as executeGetChannelProduct } from \"../../utils/channelProviderAdapter\";\n\nasync function getChannelProduct(\n root: any,\n { channelId, productId, variantId }: {\n channelId: string;\n productId?: string;\n variantId?: string;\n },\n context: any\n) {\n // Fetch the channel using the provided channelId\n const channel = await context.query.Channel.findOne({\n where: { id: channelId },\n query: \"id domain accessToken platform { id getProductFunction }\",\n });\n\n if (!channel) {\n throw new Error(\"Channel not found\");\n }\n\n if (!channel.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n // Prepare platform configuration\n const platformConfig = {\n domain: channel.domain,\n accessToken: channel.accessToken,\n getProductFunction: channel.platform.getProductFunction,\n ...channel.metadata,\n };\n\n try {\n const result = await executeGetChannelProduct({\n platform: platformConfig,\n productId: productId!,\n variantId: variantId,\n });\n\n return result.product;\n } catch (error: any) {\n throw new Error(`Failed to get channel product: ${error.message}`);\n }\n}\n\nexport default getChannelProduct;", "\"use server\";\n\nimport { getShopProduct } from \"../../utils/shopProviderAdapter\";\n\nasync function getShopProductQuery(\n root: any,\n { shopId, productId, variantId }: { shopId: string; productId: string; variantId?: string },\n context: any\n) {\n // Validate input parameters\n if (!shopId || typeof shopId !== 'string') {\n throw new Error(\"Valid shop ID is required\");\n }\n\n if (!productId || typeof productId !== 'string') {\n throw new Error(\"Valid product ID is required\");\n }\n\n const sudoContext = context.sudo();\n\n // Fetch the shop using the provided shopId\n const shop = await sudoContext.query.Shop.findOne({\n where: { id: shopId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n name\n getProductFunction\n }\n `,\n });\n\n if (!shop) {\n throw new Error(\"Shop not found\");\n }\n\n if (!shop.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n if (!shop.platform.getProductFunction) {\n throw new Error(\"Get product function not configured.\");\n }\n\n // Prepare platform configuration\n const platformConfig = {\n domain: shop.domain,\n accessToken: shop.accessToken,\n getProductFunction: shop.platform.getProductFunction,\n ...shop.metadata,\n };\n\n try {\n const result = await getShopProduct({\n platform: platformConfig,\n productId: productId,\n variantId: variantId,\n });\n\n // Extract product data from result\n const productData = result.product || result;\n\n // Enhance the result with inventory information and platform data\n return {\n ...productData,\n shopId: shop.id,\n shopDomain: shop.domain,\n platformName: shop.platform.name,\n fetchedAt: new Date().toISOString(),\n // Include live inventory levels if available\n inventoryLevel: productData.inventory || null,\n inventoryTracked: productData.inventoryTracked || false,\n // Include pricing information\n price: productData.price || null,\n compareAtPrice: productData.compareAtPrice || null,\n // Include availability\n availableForSale: productData.availableForSale || false,\n };\n } catch (error) {\n console.error(\"Error getting shop product:\", error);\n throw new Error(`Failed to get product from ${shop.platform.name}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n\nexport default getShopProductQuery;", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport {\n json,\n relationship,\n select,\n text,\n timestamp,\n virtual,\n} from \"@keystone-6/core/fields\";\nimport { graphql } from \"@keystone-6/core\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { getBaseUrl } from '../../dashboard/lib/getBaseUrl';\nimport { executeShopAdapterFunction } from '../utils/shopProviderAdapter';\n\nexport const Shop = list({\n access: {\n operation: {\n query: permissions.canSeeOtherShops,\n create: permissions.canCreateShops,\n update: permissions.canManageShops,\n delete: permissions.canManageShops,\n },\n filter: {\n query: rules.canReadShops,\n update: rules.canManageShops,\n delete: rules.canManageShops,\n },\n },\n ui: {\n listView: {\n initialColumns: [\"name\", \"domain\", \"platform\", \"linkMode\"],\n },\n },\n fields: {\n name: text({\n validation: { isRequired: true },\n }),\n domain: text(),\n accessToken: text({\n ui: {\n displayMode: \"textarea\",\n },\n }),\n refreshToken: text({\n ui: {\n displayMode: \"textarea\",\n description: \"Long-lived OAuth refresh token (30 days)\",\n },\n }),\n tokenExpiresAt: timestamp({\n ui: {\n description: \"When the current access token expires\",\n },\n }),\n linkMode: select({\n options: [\n { label: \"Sequential\", value: \"sequential\" },\n { label: \"Simultaneous\", value: \"simultaneous\" },\n ],\n defaultValue: \"sequential\",\n }),\n metadata: json({\n defaultValue: {},\n }),\n\n // Relationships\n platform: relationship({\n ref: \"ShopPlatform.shops\",\n }),\n user: relationship({\n ref: \"User.shops\",\n hooks: {\n resolveInput: ({ operation, resolvedData, context }) => {\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n links: relationship({\n ref: \"Link.shop\",\n many: true,\n }),\n orders: relationship({\n ref: \"Order.shop\",\n many: true,\n }),\n shopItems: relationship({\n ref: \"ShopItem.shop\",\n many: true,\n }),\n\n // Virtual field for webhooks with proper base URL\n webhooks: virtual({\n field: graphql.field({\n type: graphql.JSON,\n async resolve(item: any, args: any, context: any): Promise {\n try {\n const recommendedWebhooks = [\n {\n callbackUrl: `/api/handlers/shop/create-order/${item.id}`,\n topic: \"ORDER_CREATED\",\n description: \"When an order is created on this shop, Openship will create the order to be fulfilled.\",\n },\n {\n callbackUrl: `/api/handlers/shop/cancel-order/${item.id}`,\n topic: \"ORDER_CANCELLED\",\n description: \"When an order is cancelled on this shop, Openship will mark the order status cancelled\",\n },\n {\n callbackUrl: `/api/handlers/shop/cancel-order/${item.id}`,\n topic: \"ORDER_CHARGEBACKED\",\n description: \"When an order is chargebacked on this shop, Openship will mark the order status cancelled\",\n },\n ];\n\n // Get platform data with relationships resolved\n const shopWithPlatform = await context.query.Shop.findOne({\n where: { id: item.id },\n query: 'platform { getWebhooksFunction }'\n });\n\n if (!shopWithPlatform?.platform?.getWebhooksFunction) {\n return {\n success: false,\n error: \"Get webhooks function not configured\",\n recommendedWebhooks\n } as any;\n }\n\n const platformConfig = {\n domain: item.domain,\n accessToken: item.accessToken,\n getWebhooksFunction: shopWithPlatform.platform.getWebhooksFunction,\n ...(item.metadata || {}),\n };\n\n const webhooksResult = await executeShopAdapterFunction({\n platform: platformConfig,\n functionName: 'getWebhooksFunction',\n args: {},\n });\n\n return {\n success: true,\n data: { webhooks: webhooksResult.webhooks || [] },\n recommendedWebhooks\n } as any;\n } catch (error) {\n console.error('Error in webhooks virtual field:', error);\n return {\n success: false,\n error: (error as any)?.message || 'Unknown error',\n recommendedWebhooks: [\n {\n callbackUrl: `/api/handlers/shop/create-order/${item.id}`,\n topic: \"ORDER_CREATED\",\n description: \"When an order is created on this shop, Openship will create the order to be fulfilled.\",\n },\n {\n callbackUrl: `/api/handlers/shop/cancel-order/${item.id}`,\n topic: \"ORDER_CANCELLED\",\n description: \"When an order is cancelled on this shop, Openship will mark the order status cancelled\",\n },\n {\n callbackUrl: `/api/handlers/shop/cancel-order/${item.id}`,\n topic: \"ORDER_CHARGEBACKED\",\n description: \"When an order is chargebacked on this shop, Openship will mark the order status cancelled\",\n },\n ]\n } as any;\n }\n },\n }),\n }),\n\n ...trackingFields,\n },\n});\n", "import {\n integer,\n text,\n relationship,\n virtual,\n float,\n} from \"@keystone-6/core/fields\";\nimport { graphql, list } from \"@keystone-6/core\";\nimport { isSignedIn, rules, permissions } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { getShopProduct } from \"../extendGraphqlSchema/queries\";\n\nexport const ShopItem = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: isSignedIn,\n },\n filter: {\n query: rules.canReadMatches,\n update: rules.canUpdateMatches,\n delete: rules.canUpdateMatches,\n },\n },\n fields: {\n quantity: integer(),\n productId: text(),\n variantId: text(),\n lineItemId: text(),\n externalDetails: virtual({\n field: graphql.field({\n type: graphql.object()({\n name: \"ShopProduct\",\n fields: {\n image: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.image }),\n title: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.title }),\n productId: graphql.field({ type: graphql.ID, resolve: (parent: any) => parent.productId }),\n variantId: graphql.field({ type: graphql.ID, resolve: (parent: any) => parent.variantId }),\n price: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.price }),\n availableForSale: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.availableForSale }),\n productLink: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.productLink }),\n inventory: graphql.field({ type: graphql.Int, resolve: (parent: any) => parent.inventory }),\n inventoryTracked: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.inventoryTracked }),\n error: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.error }),\n },\n }),\n resolve: async (item: any, args: any, context: any): Promise => {\n const shopItem = await context.query.ShopItem.findOne({\n where: { id: item.id },\n query: \"shop { id }\",\n });\n\n if (!shopItem?.shop) {\n console.error(\"Shop not associated or missing.\");\n return { error: \"Shop not associated or missing.\" };\n }\n\n const shopId = shopItem.shop.id;\n\n try {\n const product = await getShopProduct(\n null,\n {\n shopId: shopId,\n productId: item.productId,\n variantId: item.variantId,\n },\n context\n );\n return product;\n } catch (error) {\n console.error(\"Failed to fetch external details:\", error);\n return { error: \"Failed to fetch external details.\" };\n }\n },\n }),\n ui: {\n query:\n \"{ image title productId variantId price availableForSale productLink inventory inventoryTracked error }\", // Adjust UI query as needed\n },\n }),\n matches: relationship({ ref: \"Match.input\", many: true }),\n shop: relationship({ ref: \"Shop.shopItems\" }),\n user: relationship({\n ref: \"User.shopItems\",\n hooks: {\n resolveInput({ operation, resolvedData, context }) {\n // Default to the currently logged in user on create.\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session?.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n ...trackingFields,\n },\n db: {\n extendPrismaSchema: (schema) => {\n // add a (poor) example of a multi-column unique constraint\n return schema.replace(\n /(model [^}]+)}/g,\n \"$1@@unique([quantity, productId, variantId, shopId, userId])\\n}\"\n );\n },\n },\n});", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport { relationship, timestamp, virtual } from \"@keystone-6/core/fields\";\nimport { graphql } from \"@keystone-6/core\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const Match = list({\n access: {\n operation: {\n create: permissions.canCreateMatches,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageMatches,\n },\n filter: {\n query: rules.canReadMatches,\n update: rules.canManageMatches,\n delete: rules.canManageMatches,\n },\n },\n hooks: {\n resolveInput: async ({ item, resolvedData, operation, context }) => {\n const { input, output } = resolvedData;\n\n const ensureShopItems = async (items: any) => {\n const processedItems = [];\n if (items.create) {\n for (const item of items.create) {\n let [existingItem] = await context.query.ShopItem.findMany({\n where: {\n productId: { equals: item.productId },\n variantId: { equals: item.variantId },\n quantity: { equals: item.quantity },\n shop: { id: { equals: item.shop.connect.id } },\n user: {\n id: {\n equals: item.user?.connect?.id || context.session?.itemId,\n },\n },\n },\n query: \"id\",\n });\n\n if (!existingItem) {\n existingItem = await context.query.ShopItem.createOne({\n data: item,\n query: \"id\",\n });\n }\n\n processedItems.push({ id: existingItem.id });\n }\n }\n return processedItems;\n };\n\n const ensureChannelItems = async (items: any) => {\n const processedItems = [];\n if (items.create) {\n for (const item of items.create) {\n let existingItem = await context.query.ChannelItem.findOne({\n where: {\n productId: { equals: item.productId },\n variantId: { equals: item.variantId },\n quantity: { equals: item.quantity },\n channel: { id: { equals: item.channel.connect.id } },\n user: {\n id: {\n equals: item.user?.connect?.id || context.session?.itemId,\n },\n },\n },\n query: \"id\",\n });\n\n if (!existingItem) {\n existingItem = await context.query.ChannelItem.createOne({\n data: item,\n query: \"id\",\n });\n }\n\n processedItems.push({ id: existingItem.id });\n }\n }\n return processedItems;\n };\n\n if (input && input.create) {\n const processedInput = await ensureShopItems(input);\n resolvedData.input.connect = [\n ...(resolvedData.input.connect || []),\n ...processedInput,\n ];\n delete resolvedData.input.create;\n }\n\n if (output && output.create) {\n const processedOutput = await ensureChannelItems(output);\n resolvedData.output.connect = [\n ...(resolvedData.output.connect || []),\n ...processedOutput,\n ];\n delete resolvedData.output.create;\n }\n\n // Check for duplicate matches\n const checkForDuplicate = async (inputIds: any) => {\n const existingMatches = await context.query.Match.findMany({\n where: {\n input: {\n some: { id: { in: inputIds } },\n },\n },\n query: \"id input { id }\",\n });\n\n return existingMatches.some((match) => {\n const matchInputIds = match.input.map((item: any) => item.id);\n return (\n matchInputIds.length === inputIds.length &&\n matchInputIds.every((id: any) => inputIds.includes(id))\n );\n });\n };\n\n if (operation === \"create\") {\n if (\n resolvedData.input.connect &&\n resolvedData.input.connect.length > 0\n ) {\n const inputIds = resolvedData.input.connect.map((item: any) => item.id);\n const isDuplicate = await checkForDuplicate(inputIds);\n\n if (isDuplicate) {\n throw new Error(\n \"A match with the same input combination already exists.\"\n );\n }\n }\n }\n\n if (operation === \"update\") {\n if (resolvedData.input) {\n // Fetch the current state of the match being updated\n const matchToUpdate = await context.query.Match.findOne({\n where: { id: String(item.id) },\n query: `id input { id productId variantId quantity shop { id } }`,\n });\n\n const newInputs = resolvedData.input.connect\n ? await Promise.all(\n resolvedData.input.connect.map(async (connectItem: any) => {\n return await context.query.ShopItem.findOne({\n where: { id: connectItem.id },\n query: `id productId variantId quantity shop { id }`,\n });\n })\n )\n : [];\n\n const disconnectedIds = resolvedData.input.disconnect\n ? resolvedData.input.disconnect.map((item: any) => item.id)\n : [];\n\n const remainingCurrentInputs = matchToUpdate.input.filter(\n (input: any) => !disconnectedIds.includes(input.id)\n );\n\n const combinedInputs = [...remainingCurrentInputs, ...newInputs];\n const inputIds = combinedInputs.map((item) => item.id);\n\n const isDuplicate = await checkForDuplicate(inputIds);\n\n if (isDuplicate) {\n throw new Error(\n \"A match with the same input combination already exists.\"\n );\n }\n }\n }\n\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n resolvedData.user = { connect: { id: context.session.itemId } };\n }\n\n return resolvedData;\n },\n },\n ui: {\n listView: {\n initialColumns: [\"input\", \"output\", \"user\"],\n },\n },\n fields: {\n // Virtual fields for match status\n outputPriceChanged: virtual({\n field: graphql.field({\n type: graphql.String,\n resolve() {\n return \"Price change detection for output items\";\n },\n }),\n ui: {\n itemView: { fieldMode: \"read\" },\n listView: { fieldMode: \"hidden\" },\n },\n }),\n inventoryNeedsToBeSynced: virtual({\n field: graphql.field({\n type: graphql.object()({\n name: \"MatchInventoryData\",\n fields: {\n syncEligible: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.syncEligible }),\n sourceQuantity: graphql.field({ type: graphql.Int, resolve: (parent: any) => parent.sourceQuantity }),\n targetQuantity: graphql.field({ type: graphql.Int, resolve: (parent: any) => parent.targetQuantity }),\n syncNeeded: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.syncNeeded }),\n },\n }),\n async resolve(item, args, context) {\n const match = await context.query.Match.findOne({\n where: { id: String(item.id) },\n query: `\n input { quantity externalDetails { inventory } }\n output { quantity externalDetails { inventory } }\n `,\n });\n\n const result = {\n syncEligible: false,\n sourceQuantity: null,\n targetQuantity: null,\n syncNeeded: false,\n };\n\n if (match?.input?.length === 1 && match?.output?.length === 1) {\n const input = match.input[0];\n const output = match.output[0];\n\n if (\n input.quantity === 1 &&\n output.quantity === 1 &&\n input.externalDetails?.inventory !== undefined &&\n output.externalDetails?.inventory !== undefined\n ) {\n result.syncEligible = true;\n result.sourceQuantity = input.externalDetails.inventory;\n result.targetQuantity = output.externalDetails.inventory;\n }\n }\n\n result.syncNeeded = result.syncEligible && \n result.sourceQuantity !== result.targetQuantity;\n\n return result;\n },\n }),\n ui: {\n query: \"{ syncEligible sourceQuantity targetQuantity syncNeeded }\",\n itemView: { fieldMode: \"read\" },\n listView: { fieldMode: \"hidden\" },\n },\n }),\n\n // Relationships - Many-to-many between ShopItems and ChannelItems\n input: relationship({\n ref: \"ShopItem.matches\",\n many: true,\n ui: {\n displayMode: \"cards\",\n cardFields: [\"productId\", \"variantId\", \"quantity\"],\n inlineConnect: true,\n },\n }),\n output: relationship({\n ref: \"ChannelItem.matches\",\n many: true,\n ui: {\n displayMode: \"cards\",\n cardFields: [\"productId\", \"variantId\", \"quantity\", \"price\"],\n inlineConnect: true,\n },\n }),\n user: relationship({\n ref: \"User.matches\",\n }),\n\n ...trackingFields,\n },\n});\n", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport {\n integer,\n json,\n relationship,\n timestamp,\n virtual,\n} from \"@keystone-6/core/fields\";\nimport { graphql } from \"@keystone-6/core\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const Link = list({\n access: {\n operation: {\n create: permissions.canCreateLinks,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageLinks,\n },\n filter: {\n query: rules.canReadLinks,\n update: rules.canManageLinks,\n delete: rules.canManageLinks,\n },\n },\n hooks: {\n resolveInput: {\n create: ({ operation, resolvedData, context }) => {\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n return {\n ...resolvedData,\n user: { connect: { id: context.session.itemId } },\n };\n }\n return resolvedData;\n },\n },\n beforeOperation: async ({ operation, resolvedData, context }) => {\n if (operation === \"create\") {\n const shopId = resolvedData.shop.connect.id;\n\n const existingLinks = await context.query.Link.findMany({\n where: { shop: { id: { equals: shopId } } },\n });\n\n // Calculate the next rank value\n const nextRank =\n existingLinks.length > 0 ? existingLinks.length + 1 : 1;\n\n resolvedData.rank = nextRank;\n }\n },\n },\n ui: {\n listView: {\n initialColumns: [\"shop\", \"channel\", \"rank\"],\n },\n },\n fields: {\n // Processing order\n rank: integer({\n defaultValue: 1,\n ui: {\n description: \"Processing order - lower numbers processed first\",\n },\n }),\n\n // Filter configuration\n filters: json({\n defaultValue: [],\n ui: {\n description: \"Order filtering rules\",\n },\n }),\n customWhere: json({\n defaultValue: {},\n ui: {\n description: \"Custom where clause for order filtering\",\n },\n }),\n\n // Virtual field for dynamic where clause\n dynamicWhereClause: virtual({\n field: graphql.field({\n type: graphql.String,\n resolve() {\n return \"Generated where clause based on filters\";\n },\n }),\n ui: {\n itemView: { fieldMode: \"read\" },\n listView: { fieldMode: \"hidden\" },\n },\n }),\n\n // Relationships\n shop: relationship({\n ref: \"Shop.links\",\n ui: {\n displayMode: \"cards\",\n cardFields: [\"name\", \"domain\"],\n },\n }),\n channel: relationship({\n ref: \"Channel.links\",\n ui: {\n displayMode: \"cards\",\n cardFields: [\"name\", \"domain\"],\n },\n }),\n user: relationship({\n ref: \"User.links\",\n }),\n\n ...trackingFields,\n },\n});\n", "import { list, group, graphql } from \"@keystone-6/core\";\nimport { relationship, text, virtual, json } from \"@keystone-6/core/fields\";\nimport { isSignedIn, rules, permissions } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const ShopPlatform = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: isSignedIn,\n },\n filter: {\n query: rules.canReadShops,\n update: rules.canManageShops,\n delete: rules.canManageShops,\n },\n },\n fields: {\n name: text({ validation: { isRequired: true } }),\n ...group({\n label: \"App Credentials\",\n description:\n \"Adding these fields will enable this platform to be installed as an app by users\",\n fields: {\n appKey: text({ validation: { isRequired: true } }),\n appSecret: text({ validation: { isRequired: true } }),\n callbackUrl: virtual({\n field: graphql.field({\n type: graphql.String,\n resolve: async (item: any, args: any, context: any) => {\n // Get the base URL from the request context\n let baseUrl = '';\n \n // Try to get from request headers if available\n if (context?.req?.headers) {\n const headers = context.req.headers;\n const host = headers['x-forwarded-host'] || headers['host'];\n const protocol = headers['x-forwarded-proto'] || 'https';\n \n if (host) {\n baseUrl = `${protocol}://${host}`;\n }\n }\n \n // Fallback to environment variable or default\n if (!baseUrl) {\n baseUrl = process.env.NEXT_PUBLIC_URL || 'http://localhost:3000';\n }\n \n // Return simplified callback URL (no platform ID needed)\n return `${baseUrl}/api/oauth/callback`;\n },\n }),\n ui: {\n description:\n \"Add this URL as the redirect URI in your OAuth app settings (same for all platforms)\",\n },\n }),\n },\n }),\n ...group({\n label: \"Adapter Functions\",\n description: \"These functions link to built-in adapters, but can also be external endpoints\",\n fields: {\n searchProductsFunction: text({ validation: { isRequired: true } }),\n getProductFunction: text({ validation: { isRequired: true } }),\n searchOrdersFunction: text({ validation: { isRequired: true } }),\n updateProductFunction: text({ validation: { isRequired: true } }),\n createWebhookFunction: text({ validation: { isRequired: true } }),\n oAuthFunction: text({\n validation: { isRequired: true },\n ui: {\n description: \"Function to initiate OAuth flow for this platform\",\n },\n }),\n oAuthCallbackFunction: text({\n validation: { isRequired: true },\n ui: {\n description: \"Function to handle OAuth callback for this platform\",\n },\n }),\n createOrderWebhookHandler: text({ validation: { isRequired: true } }),\n cancelOrderWebhookHandler: text({ validation: { isRequired: true } }),\n addTrackingFunction: text({ validation: { isRequired: true } }),\n orderLinkFunction: text({\n validation: { isRequired: true },\n ui: {\n description: \"Function to generate the order link for this platform\",\n },\n }),\n addCartToPlatformOrderFunction: text({ validation: { isRequired: true } }),\n getWebhooksFunction: text({ validation: { isRequired: true } }),\n deleteWebhookFunction: text({ validation: { isRequired: true } }),\n },\n }),\n shops: relationship({ ref: \"Shop.platform\", many: true }),\n user: relationship({\n ref: \"User.shopPlatforms\",\n hooks: {\n resolveInput({ operation, resolvedData, context }) {\n // Default to the currently logged in user on create.\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session?.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n ...trackingFields,\n },\n});", "import { graphql, group, list } from \"@keystone-6/core\";\nimport { relationship, text, virtual } from \"@keystone-6/core/fields\";\nimport { isSignedIn, rules, permissions } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const ChannelPlatform = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: isSignedIn,\n },\n filter: {\n query: rules.canReadChannels,\n update: rules.canUpdateChannels,\n delete: rules.canUpdateChannels,\n },\n },\n fields: {\n name: text({ validation: { isRequired: true } }),\n ...group({\n label: \"App Credentials\",\n description:\n \"Adding these fields will enable this platform to be installed as an app by users.\",\n fields: {\n appKey: text({ validation: { isRequired: true } }),\n appSecret: text({ validation: { isRequired: true } }),\n callbackUrl: virtual({\n field: graphql.field({\n type: graphql.String,\n resolve: async (item: any, args: any, context: any) => {\n // Get the base URL from the request context\n let baseUrl = '';\n \n // Try to get from request headers if available\n if (context?.req?.headers) {\n const headers = context.req.headers;\n const host = headers['x-forwarded-host'] || headers['host'];\n const protocol = headers['x-forwarded-proto'] || 'https';\n \n if (host) {\n baseUrl = `${protocol}://${host}`;\n }\n }\n \n // Fallback to environment variable or default\n if (!baseUrl) {\n baseUrl = process.env.NEXT_PUBLIC_URL || 'http://localhost:3000';\n }\n \n // Return simplified callback URL (no platform ID needed)\n return `${baseUrl}/api/oauth/callback`;\n },\n }),\n ui: {\n description:\n \"Add this URL as the redirect URI in your OAuth app settings (same for all platforms)\",\n },\n }),\n },\n }),\n ...group({\n label: \"Adapter Functions\",\n description:\n \"These functions link to built-in adapters, but can also be external endpoints\",\n fields: {\n searchProductsFunction: text({ validation: { isRequired: true } }),\n getProductFunction: text({ validation: { isRequired: true } }),\n createPurchaseFunction: text({ validation: { isRequired: true } }),\n createWebhookFunction: text({ validation: { isRequired: true } }),\n oAuthFunction: text({\n validation: { isRequired: true },\n ui: {\n description: \"Function to initiate OAuth flow for this platform\",\n },\n }),\n oAuthCallbackFunction: text({\n validation: { isRequired: true },\n ui: {\n description: \"Function to handle OAuth callback for this platform\",\n },\n }),\n createTrackingWebhookHandler: text({ validation: { isRequired: true } }),\n cancelPurchaseWebhookHandler: text({ validation: { isRequired: true } }),\n getWebhooksFunction: text({ validation: { isRequired: true } }),\n deleteWebhookFunction: text({ validation: { isRequired: true } }),\n },\n }),\n channels: relationship({ ref: \"Channel.platform\", many: true }),\n user: relationship({\n ref: \"User.channelPlatforms\",\n hooks: {\n resolveInput({ operation, resolvedData, context }) {\n // Default to the currently logged in user on create.\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session?.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n ...trackingFields,\n },\n});", "import { User } from \"./User\";\nimport { ApiKey } from \"./ApiKey\";\nimport { Role } from \"./Role\";\nimport { Order } from \"./Order\";\nimport { TrackingDetail } from \"./TrackingDetail\";\nimport { LineItem } from \"./LineItem\";\nimport { CartItem } from \"./CartItem\";\nimport { Channel } from \"./Channel\";\nimport { ChannelItem } from \"./ChannelItem\";\nimport { Shop } from \"./Shop\";\nimport { ShopItem } from \"./ShopItem\";\nimport { Match } from \"./Match\";\nimport { Link } from \"./Link\";\nimport { ShopPlatform } from \"./ShopPlatform\";\nimport { ChannelPlatform } from \"./ChannelPlatform\";\n// Add other imports here if needed\n\n// Export individual models for direct import\nexport {\n User,\n Role,\n ApiKey,\n ShopPlatform,\n ChannelPlatform,\n Shop,\n Channel,\n Order,\n LineItem,\n CartItem,\n ShopItem,\n ChannelItem,\n Match,\n Link,\n TrackingDetail\n};\n\n// Also export as models object for compatibility\nexport const models = {\n User,\n Role,\n ApiKey,\n\n // E-commerce Platform Models\n ShopPlatform,\n ChannelPlatform,\n Shop,\n Channel,\n\n // Order Management Models\n Order,\n LineItem,\n CartItem,\n\n // Product & Inventory Models\n ShopItem,\n ChannelItem,\n Match,\n\n // Linking & Tracking Models\n Link,\n TrackingDetail,\n // Add other models here as needed\n};\n", "import { mergeSchemas } from \"@graphql-tools/schema\";\nimport {\n getMatch,\n getMatchCount,\n getShopWebhooks,\n redirectToInit,\n searchShopOrders,\n searchShopProducts,\n searchChannelProducts,\n getChannelWebhooks,\n getFilteredMatches,\n getChannelProduct,\n getShopProduct,\n} from \"./queries\";\nimport {\n addMatchToCart,\n addToCart,\n cancelOrder,\n cancelPurchase,\n matchOrder,\n overwriteMatch,\n placeOrders,\n createShopWebhook,\n deleteShopWebhook,\n updateShopProduct,\n createChannelWebhook,\n deleteChannelWebhook,\n createChannelPurchase,\n upsertMatch,\n} from \"./mutations\";\n\nconst graphql = String.raw;\n// Use graphql.tag or similar if needed to define GraphQL strings\nconst typeDefs = graphql`\n extend type Mutation {\n addToCart(\n channelId: ID\n image: String\n name: String\n price: String\n productId: String\n variantId: String\n quantity: String\n orderId: ID\n ): Order\n placeOrders(ids: [ID!]!): [Order]\n addMatchToCart(orderId: ID!): Order\n matchOrder(orderId: ID!): Match\n overwriteMatch(\n input: [ShopItemWhereInput!]\n output: [ChannelItemWhereInput!]\n ): Match\n cancelPurchase(purchaseId: String!): String\n cancelOrder(orderId: String!): String\n createShopWebhook(\n shopId: ID!\n topic: String!\n endpoint: String!\n ): CreateWebhookResponse\n deleteShopWebhook(shopId: ID!, webhookId: ID!): DeleteWebhookResponse\n updateShopProduct(\n shopId: ID!\n variantId: ID!\n productId: ID!\n price: String\n inventoryDelta: Int\n ): UpdateProductResponse\n createChannelWebhook(\n channelId: ID!\n topic: String!\n endpoint: String!\n ): CreateWebhookResponse\n deleteChannelWebhook(channelId: ID!, webhookId: ID!): DeleteWebhookResponse\n createChannelPurchase(input: CreatePurchaseInput!): CreatePurchaseResponse\n upsertMatch(data: MatchCreateInput!): Match\n }\n\n extend type Query {\n getMatch(input: [ShopItemWhereInput!]): [ChannelItemPlus!]\n getMatchCount(input: [ShopItemWhereInput!]): Int\n redirectToInit: Boolean\n searchShopProducts(shopId: ID!, searchEntry: String): [ShopProduct]\n getShopProduct(\n shopId: ID!\n variantId: String\n productId: String\n ): ShopProduct\n searchShopOrders(\n shopId: ID!\n searchEntry: String\n take: Int!\n skip: Int\n after: String\n ): ShopOrderConnection\n getShopWebhooks(shopId: ID!): [Webhook]\n searchChannelProducts(channelId: ID!, searchEntry: String): [ChannelProduct]\n getChannelProduct(\n channelId: ID!\n variantId: String\n productId: String\n ): ChannelProduct\n getChannelWebhooks(channelId: ID!): [Webhook]\n getFilteredMatches: [Match]\n }\n\n type FoundMatch {\n id: ID!\n output: [ChannelItemPlus!]\n }\n\n type ChannelItemPlus {\n quantity: Int\n productId: String\n variantId: String\n price: String\n image: String\n name: String\n channelName: String\n channelId: String\n }\n\n type ShopOrder {\n orderId: ID!\n orderName: String\n link: String\n date: String\n firstName: String\n lastName: String\n streetAddress1: String\n streetAddress2: String\n city: String\n state: String\n zip: String\n country: String\n email: String\n cartItems: [ShopCartItem]\n cursor: String\n lineItems: [ShopLineItem]\n fulfillments: [Fulfillment]\n note: String\n totalPrice: String\n }\n\n type ShopOrderConnection {\n orders: [ShopOrder]\n hasNextPage: Boolean\n }\n\n type ChannelPlus {\n id: ID!\n name: String!\n }\n\n type ShopCartItem {\n productId: String\n variantId: String\n quantity: Int\n price: String\n name: String\n image: String\n channel: ChannelPlus\n }\n\n type ShopLineItem {\n name: String\n quantity: Int\n price: String\n image: String\n productId: String\n variantId: String\n sku: String\n lineItemId: String\n }\n\n type Fulfillment {\n company: String\n number: String\n url: String\n }\n\n type Webhook {\n id: ID!\n callbackUrl: String!\n createdAt: DateTime!\n topic: String!\n includeFields: [String!]\n }\n\n type CreateWebhookResponse {\n success: Boolean\n error: String\n webhookId: ID\n }\n\n type DeleteWebhookResponse {\n success: Boolean\n error: String\n }\n\n type UpdateProductResponse {\n success: Boolean\n error: String\n updatedVariant: ProductVariant\n }\n\n type ProductVariant {\n price: String\n inventory: Int\n }\n\n input CreatePurchaseInput {\n shopId: ID!\n cartItems: [CartItemInput!]!\n email: String!\n address: AddressInput!\n orderId: ID!\n }\n\n input CartItemInput {\n variantId: ID!\n quantity: Int!\n }\n\n input AddressInput {\n firstName: String!\n lastName: String!\n streetAddress1: String!\n streetAddress2: String\n city: String!\n state: String!\n zip: String!\n country: String!\n }\n\n type CreatePurchaseResponse {\n success: Boolean\n error: String\n purchaseId: ID\n }\n`;\n\nexport const extendGraphqlSchema = (baseSchema: any) =>\n mergeSchemas({\n schemas: [baseSchema],\n typeDefs,\n resolvers: {\n Mutation: {\n addToCart,\n placeOrders,\n addMatchToCart,\n matchOrder,\n overwriteMatch,\n cancelPurchase,\n cancelOrder,\n createShopWebhook,\n deleteShopWebhook,\n updateShopProduct,\n createChannelWebhook,\n deleteChannelWebhook,\n createChannelPurchase,\n upsertMatch,\n },\n Query: {\n getMatch,\n getMatchCount,\n redirectToInit,\n searchShopProducts,\n searchShopOrders,\n getShopWebhooks,\n searchChannelProducts,\n getChannelWebhooks,\n getFilteredMatches,\n getChannelProduct,\n getShopProduct,\n },\n },\n });", "import type { KeystoneContext } from '@keystone-6/core/types';\n\ninterface AddToCartArgs {\n channelId: string;\n image?: string;\n name: string;\n price: string;\n productId: string;\n variantId: string;\n quantity: string;\n orderId: string;\n}\n\nasync function addToCart(\n root: any,\n { channelId, image, name, price, productId, variantId, quantity, orderId }: AddToCartArgs,\n context: KeystoneContext\n) {\n // 1. Query the current user see if they are signed in\n const session = context.session;\n if (!session?.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n // 2. Query the current users cart\n const allCartItems = await context.query.CartItem.findMany({\n where: {\n order: { id: { equals: orderId } },\n channel: { id: { equals: channelId } },\n user: { id: { equals: session.itemId } },\n productId: { equals: productId },\n variantId: { equals: variantId },\n status: { not: { equals: \"CANCELLED\" } },\n purchaseId: { equals: \"\" },\n url: { equals: \"\" },\n },\n query: \"id quantity\",\n });\n\n const [existingCartItem] = allCartItems;\n if (existingCartItem) {\n console.log(\n `There are already ${existingCartItem.quantity}, increment by 1!`\n );\n\n await context.query.CartItem.updateOne({\n where: { id: existingCartItem.id },\n data: {\n quantity: existingCartItem.quantity + parseInt(quantity, 10),\n },\n });\n\n return await context.db.Order.findOne({\n where: {\n id: orderId,\n },\n });\n }\n\n await context.query.CartItem.createOne({\n data: {\n price: price,\n productId,\n variantId,\n quantity: parseInt(quantity, 10),\n image,\n name,\n user: { connect: { id: session.itemId } },\n order: { connect: { id: orderId } },\n channel: { connect: { id: channelId } },\n },\n });\n\n return await context.db.Order.findOne({\n where: {\n id: orderId,\n },\n });\n}\n\nexport default addToCart;", "import type { KeystoneContext } from '@keystone-6/core/types';\n\ninterface CancelOrderArgs {\n orderId: string;\n}\n\nasync function cancelOrder(\n root: any,\n { orderId }: CancelOrderArgs,\n context: KeystoneContext\n) {\n try {\n // 1. Update order status to cancelled\n await context.query.Order.updateOne({\n where: { id: orderId },\n data: {\n status: \"CANCELLED\",\n },\n });\n\n // 2. Cancel all associated cart items\n const cartItems = await context.query.CartItem.findMany({\n where: {\n order: { id: { equals: orderId } },\n },\n query: \"id\",\n });\n\n for (const cartItem of cartItems) {\n await context.query.CartItem.updateOne({\n where: { id: cartItem.id },\n data: {\n status: \"CANCELLED\",\n },\n });\n }\n\n return \"Order cancelled successfully\";\n } catch (error: any) {\n throw new Error(`Failed to cancel order: ${error.message}`);\n }\n}\n\nexport default cancelOrder;", "import type { KeystoneContext } from '@keystone-6/core/types';\n\ninterface CancelPurchaseArgs {\n purchaseId: string;\n}\n\nasync function cancelPurchase(\n root: any,\n { purchaseId }: CancelPurchaseArgs,\n context: KeystoneContext\n) {\n try {\n // 1. Find cart items with this purchase ID\n const cartItems = await context.query.CartItem.findMany({\n where: {\n purchaseId: { equals: purchaseId },\n },\n query: \"id\",\n });\n\n // 2. Update cart items to cancelled status\n for (const cartItem of cartItems) {\n await context.query.CartItem.updateOne({\n where: { id: cartItem.id },\n data: {\n status: \"CANCELLED\",\n },\n });\n }\n\n return \"Purchase cancelled successfully\";\n } catch (error: any) {\n throw new Error(`Failed to cancel purchase: ${error.message}`);\n }\n}\n\nexport default cancelPurchase;", "\"use server\";\n\nasync function findChannelItems({ cartItems, userId, context }: {\n cartItems: Array;\n userId: string;\n context: any;\n}) {\n const arr = [];\n\n for (const {\n name,\n image,\n channelName,\n status,\n quantity,\n channelId,\n productId,\n variantId,\n price, // ensure price is string if present\n ...rest\n } of cartItems) {\n const [existingChannelItem] = await context.query.ChannelItem.findMany({\n where: {\n channel: { id: { equals: channelId } },\n user: { id: { equals: userId } },\n quantity: { equals: parseInt(quantity) },\n productId: { equals: productId },\n variantId: { equals: variantId },\n // ...rest,\n },\n });\n\n if (existingChannelItem) {\n arr.push({ id: existingChannelItem.id });\n } else {\n const createChannelItem = await context.query.ChannelItem.createOne({\n data: {\n channel: { connect: { id: channelId } },\n quantity: parseInt(quantity),\n productId,\n variantId,\n ...(price !== undefined ? { price: String(price) } : {}),\n ...rest,\n },\n });\n arr.push({ id: createChannelItem.id });\n }\n }\n\n return arr;\n}\n\nasync function findShopItems({ lineItems, userId, context }: {\n lineItems: Array;\n userId: string;\n context: any;\n}) {\n const arr = [];\n\n for (const {\n name,\n image,\n channelName,\n price, // REMOVE for ShopItem\n quantity,\n channelId,\n productId,\n variantId,\n ...rest\n } of lineItems) {\n // Remove price from rest if present\n const { price: _omitPrice, ...restWithoutPrice } = rest;\n const [existingShopItem] = await context.query.ShopItem.findMany({\n where: {\n shop: { id: { equals: channelId } },\n user: { id: { equals: userId } },\n quantity: { equals: parseInt(quantity) },\n productId: { equals: productId },\n variantId: { equals: variantId },\n ...restWithoutPrice,\n },\n });\n\n if (existingShopItem) {\n arr.push({ id: existingShopItem.id });\n } else {\n const createShopItem = await context.query.ShopItem.createOne({\n data: {\n shop: { connect: { id: channelId } },\n quantity: parseInt(quantity),\n productId,\n variantId,\n ...restWithoutPrice,\n },\n });\n arr.push({ id: createShopItem.id });\n }\n }\n\n return arr;\n}\n\nasync function matchOrder(root: any, { orderId }: { orderId: string }, context: any) {\n const sesh = context.session;\n\n if (!sesh.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n const order = await context.query.Order.findOne({\n where: {\n id: orderId,\n },\n query: `\n cartItems {\n channel {\n id\n }\n image\n price\n id\n quantity\n productId\n variantId\n }\n shop {\n id\n }\n lineItems {\n image\n price\n id\n quantity\n productId\n variantId\n lineItemId\n }\n `,\n });\n\n const shopItemConnect = await findShopItems({\n lineItems: order.lineItems.map(\n ({ id, lineItemId, orderId, userId, updatedAt, createdAt, ...rest }: any) => {\n // turn into NullFilter values ({ equal }) for findMany\n // const restNested = Object.keys(rest).reduce(\n // (acc, key) => ({\n // ...acc,\n // ...{ [key]: { equals: rest[key] } },\n // }),\n // {}\n // );\n return {\n ...rest,\n channelId: order.shop.id,\n };\n }\n ),\n userId: sesh.itemId,\n context,\n });\n\n const channelItemConnect = await findChannelItems({\n cartItems: order.cartItems.map(\n ({\n id,\n lineItemId,\n orderId,\n userId,\n updatedAt,\n createdAt,\n url,\n error: cartItemError,\n purchaseId,\n channel,\n ...rest\n }: any) => {\n return {\n ...rest,\n channelId: channel.id,\n };\n }\n ),\n userId: sesh.itemId,\n context,\n });\n\n const existingMatches = await context.query.Match.findMany({\n where: {\n user: {\n id: { equals: sesh.itemId },\n },\n AND: order.lineItems.map(({ productId, variantId, quantity }: any) => ({\n input: {\n some: {\n productId: { equals: productId },\n variantId: { equals: variantId },\n quantity: { equals: parseInt(quantity) },\n },\n },\n })),\n },\n query: ` \n id\n inputCount\n outputCount\n input {\n id\n quantity\n productId\n variantId\n shop {\n id\n }\n user {\n id\n }\n }\n output {\n id\n quantity\n productId\n variantId\n price\n channel {\n id\n domain\n accessToken\n platform {\n id\n }\n }\n user {\n id\n }\n }\n `,\n });\n\n const [existingMatch] = existingMatches.filter(\n (match: any) => match.input.length === order.lineItems.length\n );\n\n if (existingMatch) {\n await context.query.Match.deleteOne({\n where: { id: existingMatch.id },\n });\n }\n\n const newMatch = await context.db.Match.createOne({\n data: {\n input: { connect: shopItemConnect },\n output: { connect: channelItemConnect },\n user: {\n connect: {\n id: sesh.itemId,\n },\n },\n },\n });\n\n return newMatch;\n}\n\nexport default matchOrder;", "import type { KeystoneContext } from '@keystone-6/core/types';\n\ninterface OverwriteMatchArgs {\n input: Array<{\n productId?: string;\n variantId?: string;\n [key: string]: any;\n }>;\n output: Array<{\n productId?: string;\n variantId?: string;\n [key: string]: any;\n }>;\n}\n\nasync function overwriteMatch(\n root: any,\n { input, output }: OverwriteMatchArgs,\n context: KeystoneContext\n) {\n // 1. Query the current user see if they are signed in\n const session = context.session;\n if (!session?.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n // 2. Find existing match with same input criteria\n const existingMatches = await context.query.Match.findMany({\n where: {\n input: {\n every: {\n OR: input.map(item => ({\n AND: [\n { productId: { equals: item.productId } },\n { variantId: { equals: item.variantId } }\n ]\n }))\n }\n }\n },\n query: \"id\",\n });\n\n // 3. Delete existing matches\n for (const match of existingMatches) {\n await context.query.Match.deleteOne({\n where: { id: match.id },\n });\n }\n\n // 4. Create new match\n const match = await context.query.Match.createOne({\n data: {\n user: { connect: { id: session.itemId } },\n input: {\n create: input.map(item => ({\n productId: item.productId,\n variantId: item.variantId,\n user: { connect: { id: session.itemId } },\n }))\n },\n output: {\n create: output.map(item => ({\n productId: item.productId,\n variantId: item.variantId,\n price: item.price,\n quantity: item.quantity,\n name: item.name,\n image: item.image,\n channel: { connect: { id: item.channelId } },\n user: { connect: { id: session.itemId } },\n }))\n }\n },\n query: \"id\",\n });\n\n return match;\n}\n\nexport default overwriteMatch;", "import { placeMultipleOrders } from '../../lib/placeMultipleOrders';\n\nasync function placeOrders(root: any, { ids }: { ids: string[] }, context: any) {\n // 1. Query the current user see if they are signed in\n const sesh = context.session;\n if (!sesh.itemId) {\n throw new Error('You must be logged in to do this!');\n }\n\n const processedOrders = await placeMultipleOrders({\n ids,\n query: context.query,\n });\n\n return processedOrders;\n}\n\nexport default placeOrders;", "import { createShopWebhook as executeCreateShopWebhook } from \"../../utils/shopProviderAdapter\";\n\ninterface CreateShopWebhookArgs {\n shopId: string;\n topic: string;\n endpoint: string;\n}\n\nasync function createShopWebhook(\n root: any,\n { shopId, topic, endpoint }: CreateShopWebhookArgs,\n context: any\n) {\n\n try {\n const sudoContext = context.sudo();\n\n \n // Fetch the shop using the provided shopId\n const shop = await sudoContext.query.Shop.findOne({\n where: { id: shopId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n name\n createWebhookFunction\n }\n `,\n });\n\n\n if (!shop) {\n return { success: false, error: \"Shop not found\" };\n }\n\n if (!shop.platform) {\n return { success: false, error: \"Platform configuration not specified.\" };\n }\n\n if (!shop.platform.createWebhookFunction) {\n return { success: false, error: \"Create webhook function not configured.\" };\n }\n\n // Prepare platform configuration (matching getShopProduct pattern)\n const platformConfig = {\n domain: shop.domain,\n accessToken: shop.accessToken,\n createWebhookFunction: shop.platform.createWebhookFunction,\n ...shop.metadata,\n };\n\n const result = await executeCreateShopWebhook({\n platform: platformConfig,\n endpoint,\n events: [topic],\n });\n\n\n return { success: true, webhookId: result.webhookId };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n}\n\nexport default createShopWebhook;", "import { deleteShopWebhook as executeDeleteShopWebhook } from \"../../utils/shopProviderAdapter\";\n\ninterface DeleteShopWebhookArgs {\n shopId: string;\n webhookId: string;\n}\n\nasync function deleteShopWebhook(\n root: any,\n { shopId, webhookId }: DeleteShopWebhookArgs,\n context: any\n) {\n try {\n // Fetch the shop using the provided shopId\n const shop = await context.query.Shop.findOne({\n where: { id: shopId },\n query: \"id domain accessToken platform { id deleteWebhookFunction }\",\n });\n\n if (!shop) {\n return { success: false, error: \"Shop not found\" };\n }\n\n if (!shop.platform) {\n return { success: false, error: \"Platform configuration not specified.\" };\n }\n\n await executeDeleteShopWebhook({\n platform: {\n ...shop.platform,\n domain: shop.domain,\n accessToken: shop.accessToken,\n },\n webhookId,\n });\n\n return { success: true };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n}\n\nexport default deleteShopWebhook;", "import { updateShopProduct as executeUpdateShopProduct } from \"../../utils/shopProviderAdapter\";\n\nasync function updateShopProduct(\n root: any,\n { shopId, variantId, productId, price, inventoryDelta }: {\n shopId: string;\n variantId: string;\n productId: string;\n price?: string;\n inventoryDelta?: number;\n },\n context: any\n) {\n // Fetch the shop using the provided shopId\n const shop = await context.query.Shop.findOne({\n where: { id: shopId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n updateProductFunction\n }\n `,\n });\n\n if (!shop) {\n throw new Error(\"Shop not found\");\n }\n\n if (!shop.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n // Create platform config with domain, accessToken, and metadata\n const platformConfig = {\n domain: shop.domain,\n accessToken: shop.accessToken,\n ...shop.metadata,\n };\n\n try {\n const result = await executeUpdateShopProduct({\n platform: {\n ...shop.platform,\n ...platformConfig,\n },\n productId,\n variantId,\n inventory: inventoryDelta,\n price,\n });\n\n if (result.error) {\n throw new Error(result.error);\n }\n\n return { success: true, updatedVariant: result.updatedVariant };\n } catch (error: any) {\n throw new Error(`Failed to update product: ${error.message}`);\n }\n}\n\nexport default updateShopProduct;", "import { createChannelWebhook as executeCreateChannelWebhook } from \"../../utils/channelProviderAdapter\";\n\ninterface CreateChannelWebhookArgs {\n channelId: string;\n topic: string;\n endpoint: string;\n}\n\nasync function createChannelWebhook(\n root: any,\n { channelId, topic, endpoint }: CreateChannelWebhookArgs,\n context: any\n) {\n try {\n const sudoContext = context.sudo();\n\n // Fetch the channel using the provided channelId\n const channel = await sudoContext.query.Channel.findOne({\n where: { id: channelId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n name\n createWebhookFunction\n }\n `,\n });\n\n if (!channel) {\n return { success: false, error: \"Channel not found\" };\n }\n\n if (!channel.platform) {\n return { success: false, error: \"Platform configuration not specified.\" };\n }\n\n if (!channel.platform.createWebhookFunction) {\n return { success: false, error: \"Create webhook function not configured.\" };\n }\n\n // Prepare platform configuration (matching working pattern)\n const platformConfig = {\n domain: channel.domain,\n accessToken: channel.accessToken,\n createWebhookFunction: channel.platform.createWebhookFunction,\n ...channel.metadata,\n };\n\n const result = await executeCreateChannelWebhook({\n platform: platformConfig,\n endpoint,\n events: [topic],\n });\n\n return { success: true, webhookId: result.webhookId };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n}\n\nexport default createChannelWebhook;", "import { deleteChannelWebhook as executeDeleteChannelWebhook } from \"../../utils/channelProviderAdapter\";\n\ninterface DeleteChannelWebhookArgs {\n channelId: string;\n webhookId: string;\n}\n\nasync function deleteChannelWebhook(\n root: any,\n { channelId, webhookId }: DeleteChannelWebhookArgs,\n context: any\n) {\n try {\n // Fetch the channel using the provided channelId\n const channel = await context.query.Channel.findOne({\n where: { id: channelId },\n query: \"id domain accessToken platform { id deleteWebhookFunction }\",\n });\n\n if (!channel) {\n return { success: false, error: \"Channel not found\" };\n }\n\n if (!channel.platform) {\n return { success: false, error: \"Platform configuration not specified.\" };\n }\n\n await executeDeleteChannelWebhook({\n platform: {\n ...channel.platform,\n domain: channel.domain,\n accessToken: channel.accessToken,\n },\n webhookId,\n });\n\n return { success: true };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n}\n\nexport default deleteChannelWebhook;", "import { createChannelPurchase as executeChannelPurchase } from \"../../utils/channelProviderAdapter\";\n\nasync function createChannelPurchase(root: any, { input }: { input: any }, context: any) {\n const { channelId, cartItems, address, notes, ...otherData } = input;\n\n // Fetch the channel using the provided channelId\n const channel = await context.query.Channel.findOne({\n where: { id: channelId },\n query: \"id domain accessToken platform { id createPurchaseFunction }\",\n });\n\n if (!channel) {\n throw new Error(\"Channel not found\");\n }\n\n if (!channel.platform) {\n throw new Error(\"Channel platform not configured.\");\n }\n\n try {\n const result = await executeChannelPurchase({\n platform: channel.platform,\n cartItems,\n shipping: address,\n notes,\n });\n\n if (result.error) {\n throw new Error(result.error);\n }\n\n return { success: true, purchaseId: result.purchaseId };\n } catch (error: any) {\n throw new Error(`Failed to create purchase: ${error.message}`);\n }\n}\n\nexport default createChannelPurchase;", "const upsertMatch = async (_: any, { data }: { data: any }, context: any) => {\n const { input, output } = data;\n // Ensure ShopItems\n const ensureShopItems = async (items: any[]) => {\n const processedItems = [];\n for (const item of items) {\n let [existingItem] = await context.query.ShopItem.findMany({\n where: {\n productId: { equals: item.productId },\n variantId: { equals: item.variantId },\n quantity: { equals: item.quantity },\n shop: { id: { equals: item.shop.connect.id } },\n user: { id: { equals: item.user?.connect?.id || context.session?.itemId } },\n },\n query: \"id\",\n });\n\n if (!existingItem) {\n existingItem = await context.db.ShopItem.createOne({\n data: item,\n query: \"id\",\n });\n }\n\n processedItems.push({ id: existingItem.id });\n }\n return processedItems;\n };\n\n // Ensure ChannelItems\n const ensureChannelItems = async (items: any[]) => {\n const processedItems = [];\n for (const item of items) {\n let [existingItem] = await context.query.ChannelItem.findMany({\n where: {\n productId: { equals: item.productId },\n variantId: { equals: item.variantId },\n quantity: { equals: item.quantity },\n channel: { id: { equals: item.channel.connect.id } },\n user: { id: { equals: item.user?.connect?.id || context.session?.itemId } },\n },\n query: \"id\",\n });\n\n if (!existingItem) {\n existingItem = await context.query.ChannelItem.createOne({\n data: item,\n query: \"id\",\n });\n }\n\n processedItems.push({ id: existingItem.id });\n }\n return processedItems;\n };\n\n // Process inputs and outputs\n const processedInput = await ensureShopItems(input.create);\n const processedOutput = await ensureChannelItems(output.create);\n\n const inputIds = processedInput.map((item) => item.id);\n const outputIds = processedOutput.map((item) => item.id);\n\n // Check for existing match\n const existingMatches = await context.query.Match.findMany({\n where: {\n input: {\n some: { id: { in: inputIds } },\n },\n },\n query: \"id input { id } output { id }\",\n });\n\n const duplicateMatch = existingMatches.find((match: any) => {\n const matchInputIds = match.input.map((i: any) => i.id);\n return (\n matchInputIds.length === inputIds.length &&\n matchInputIds.every((id: string) => inputIds.includes(id))\n );\n });\n\n if (duplicateMatch) {\n // Update existing match\n await context.query.Match.updateOne({\n where: { id: duplicateMatch.id },\n data: {\n output: {\n disconnect: duplicateMatch.output.map((o: any) => ({ id: o.id })),\n connect: outputIds.map((id) => ({ id })),\n },\n },\n });\n return duplicateMatch;\n } else {\n // Create new match\n return await context.query.Match.createOne({\n data: {\n input: { connect: inputIds.map((id) => ({ id })) },\n output: { connect: outputIds.map((id) => ({ id })) },\n },\n });\n }\n};\n\nexport default upsertMatch;", "'use server' \n\nimport { createTransport, getTestMessageUrl } from \"nodemailer\";\n\n// Utility function to get base URL for emails\nfunction getBaseUrlForEmails(): string {\n if (process.env.SMTP_STORE_LINK) {\n return process.env.SMTP_STORE_LINK;\n }\n \n // Fallback warning - this should be set in production\n console.warn('SMTP_STORE_LINK not set. Please add SMTP_STORE_LINK to your environment variables for email links to work properly.');\n return '';\n}\n\nconst transport = createTransport({\n // @ts-ignore\n host: process.env.SMTP_HOST,\n port: process.env.SMTP_PORT,\n auth: {\n user: process.env.SMTP_USER,\n pass: process.env.SMTP_PASSWORD,\n },\n});\n\nfunction passwordResetEmail({ url }: { url: string }): string {\n const backgroundColor = \"#f9f9f9\";\n const textColor = \"#444444\";\n const mainBackgroundColor = \"#ffffff\";\n const buttonBackgroundColor = \"#346df1\";\n const buttonBorderColor = \"#346df1\";\n const buttonTextColor = \"#ffffff\";\n\n return `\n \n \n \n \n \n \n \n \n \n \n \n
\n Please click below to reset your password\n
\n \n \n \n \n
Reset Password
\n
\n If you did not request this email you can safely ignore it.\n
\n \n `;\n}\n\nexport async function sendPasswordResetEmail(resetToken: string, to: string, baseUrl?: string): Promise {\n // Use provided baseUrl or fall back to utility function\n const frontendUrl = baseUrl || getBaseUrlForEmails();\n \n // email the user a token\n const info = await transport.sendMail({\n to,\n from: process.env.SMTP_FROM,\n subject: \"Your password reset token!\",\n html: passwordResetEmail({\n url: `${frontendUrl}/dashboard/reset?token=${resetToken}`,\n }),\n });\n if (process.env.MAIL_USER?.includes(\"ethereal.email\")) {\n console.log(`\uD83D\uDCE7 Message Sent! Preview it at ${getTestMessageUrl(info as any)}`);\n }\n}"], - "mappings": "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", - "names": ["scopes", "createPurchaseFunction", "createWebhookFunction", "deleteWebhookFunction", "getProductFunction", "getWebhooksFunction", "oAuthCallbackFunction", "oAuthFunction", "scopes", "searchProductsFunction", "REQUIRED_SCOPES", "import_graphql_request", "openfront_exports", "addTrackingFunction", "createWebhookFunction", "deleteWebhookFunction", "getProductFunction", "getWebhooksFunction", "oAuthCallbackFunction", "oAuthFunction", "scopes", "searchProductsFunction", "createOpenFrontClient", "getProductImageUrl", "REQUIRED_SCOPES", "import_graphql_request", "getFreshAccessToken", "init_openfront", "shopify_exports", "addTrackingFunction", "cancelOrderWebhookHandler", "createOrderWebhookHandler", "createWebhookFunction", "deleteWebhookFunction", "getProductFunction", "getWebhooksFunction", "oAuthCallbackFunction", "oAuthFunction", "scopes", "searchOrdersFunction", "searchProductsFunction", "updateProductFunction", "REQUIRED_SCOPES", "import_graphql_request", "import_getBaseUrl", "init_shopify", "executor_exports", "globImport_ts", "init_executor", "init_", "keystone_default", "import_core", "import_fields", "scopes", "permissions", "import_fields", "import_core", "import_fields", "import_core", "import_fields", "import_core", "import_fields", "executeChannelAdapterFunction", "searchChannelProducts", "getChannelProduct", "createChannelPurchase", "createChannelWebhook", "deleteChannelWebhook", "getChannelWebhooks", "executeShopAdapterFunction", "searchShopProducts", "getShopProduct", "searchShopOrders", "updateShopProduct", "addCartToPlatformOrder", "createShopWebhook", "deleteShopWebhook", "getShopWebhooks", "createChannelPurchase", "addCartToPlatformOrder", "order", "import_core", "import_fields", "addShopTracking", "import_core", "import_fields", "import_core", "import_fields", "import_core", "import_fields", "executeChannelAdapterFunction", "import_fields", "import_core", "getMatches", "searchProductsFunction", "searchChannelProducts", "getMatches", "getShopWebhooks", "searchShopOrders", "searchShopProducts", "searchChannelProducts", "getChannelWebhooks", "getChannelProduct", "getShopProduct", "import_core", "import_fields", "executeShopAdapterFunction", "import_fields", "import_core", "import_core", "import_fields", "item", "input", "import_core", "import_fields", "import_core", "import_fields", "import_core", "import_fields", "orderId", "match", "createShopWebhook", "deleteShopWebhook", "updateShopProduct", "createChannelWebhook", "deleteChannelWebhook", "createChannelPurchase", "graphql", "Iron", "bcryptjs", "keystone_default"] + "sourcesContent": ["import { GraphQLClient, gql } from \"graphql-request\";\nimport { keystoneContext } from '@/features/keystone/context';\n\ninterface OpenFrontPlatform {\n domain: string;\n accessToken: string;\n refreshToken?: string;\n tokenExpiresAt?: Date | string;\n appKey?: string;\n appSecret?: string;\n}\n\ninterface SearchProductsArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface GetProductArgs {\n productId: string;\n variantId?: string;\n}\n\ninterface CreatePurchaseArgs {\n cartItems: any[];\n shipping: any;\n notes?: string;\n}\n\ninterface CreateWebhookArgs {\n endpoint: string;\n events: string[];\n}\n\ninterface DeleteWebhookArgs {\n webhookId: string;\n}\n\n// Helper function to get fresh access token with proper OAuth 2.0 flow\nconst getFreshAccessToken = async (platform: OpenFrontPlatform) => {\n console.log('\uD83D\uDD04 [OpenFront Channel] getFreshAccessToken called');\n console.log('\uD83D\uDD04 [OpenFront Channel] Platform domain:', platform.domain);\n console.log('\uD83D\uDD04 [OpenFront Channel] Actual access token:', platform.accessToken);\n \n // Get channel with OAuth credentials from database\n const channels = await keystoneContext.sudo().query.Channel.findMany({\n where: { \n domain: { equals: platform.domain },\n accessToken: { equals: platform.accessToken }\n },\n query: 'id refreshToken tokenExpiresAt platform { appKey appSecret }'\n });\n \n if (!channels || channels.length === 0) {\n console.log('\u26A0\uFE0F [OpenFront Channel] No matching channel found in database');\n return platform.accessToken;\n }\n \n const channel = channels[0];\n console.log('\uD83D\uDD04 [OpenFront Channel] Found channel:', channel.id);\n console.log('\uD83D\uDD04 [OpenFront Channel] Has refresh token:', !!channel.refreshToken);\n console.log('\uD83D\uDD04 [OpenFront Channel] Token expires at:', channel.tokenExpiresAt);\n console.log('\uD83D\uDD04 [OpenFront Channel] Has appKey:', !!channel.platform?.appKey);\n console.log('\uD83D\uDD04 [OpenFront Channel] Has appSecret:', !!channel.platform?.appSecret);\n console.log('\uD83D\uDD04 [OpenFront Channel] Actual refresh token:', channel.refreshToken);\n \n // If we have a refresh token, check if we need to refresh\n if (channel.refreshToken) {\n console.log('\uD83D\uDD04 [OpenFront Channel] Refresh token found, checking if refresh needed');\n \n // Check if access token has expired (if we have expiry info)\n let shouldRefresh = false;\n \n if (channel.tokenExpiresAt) {\n const expiresAt = typeof channel.tokenExpiresAt === 'string' \n ? new Date(channel.tokenExpiresAt) \n : channel.tokenExpiresAt;\n \n const now = new Date();\n shouldRefresh = expiresAt <= now;\n \n console.log('\uD83D\uDD04 [OpenFront Channel] Token expiry check:');\n console.log('\uD83D\uDD04 [OpenFront Channel] - Expires at:', expiresAt.toISOString());\n console.log('\uD83D\uDD04 [OpenFront Channel] - Current time:', now.toISOString());\n console.log('\uD83D\uDD04 [OpenFront Channel] - Should refresh:', shouldRefresh);\n } else {\n // If no expiry info, assume token needs refresh\n shouldRefresh = true;\n console.log('\uD83D\uDD04 [OpenFront Channel] No expiry info found, assuming refresh needed');\n }\n \n if (shouldRefresh) {\n console.log('\uD83D\uDD04 [OpenFront Channel] Starting token refresh process...');\n \n // Use refresh token to get new access token\n const tokenUrl = `${platform.domain}/api/oauth/token`;\n console.log('\uD83D\uDD04 [OpenFront Channel] Token URL:', tokenUrl);\n \n const formData = new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: channel.refreshToken,\n client_id: channel.platform?.appKey || \"\",\n client_secret: channel.platform?.appSecret || \"\",\n });\n\n console.log('\uD83D\uDD04 [OpenFront Channel] Refresh request params:');\n console.log('\uD83D\uDD04 [OpenFront Channel] - grant_type: refresh_token');\n console.log('\uD83D\uDD04 [OpenFront Channel] - client_id:', channel.platform?.appKey || \"NOT_SET\");\n console.log('\uD83D\uDD04 [OpenFront Channel] - client_secret:', channel.platform?.appSecret ? \"SET\" : \"NOT_SET\");\n console.log('\uD83D\uDD04 [OpenFront Channel] - refresh_token:', channel.refreshToken ? \"SET\" : \"NOT_SET\");\n\n console.log('\uD83D\uDD04 [OpenFront Channel] Making refresh token request...');\n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: formData,\n });\n\n console.log('\uD83D\uDD04 [OpenFront Channel] Refresh response status:', response.status);\n console.log('\uD83D\uDD04 [OpenFront Channel] Refresh response ok:', response.ok);\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('\uD83D\uDEA8 [OpenFront Channel] Token refresh failed:', errorText);\n console.error('\uD83D\uDEA8 [OpenFront Channel] Response status:', response.status);\n console.error('\uD83D\uDEA8 [OpenFront Channel] Response statusText:', response.statusText);\n throw new Error(`Failed to refresh access token: ${response.statusText} - ${errorText}`);\n }\n\n const tokenData = await response.json();\n console.log('\uD83D\uDD04 [OpenFront Channel] Token refresh response received');\n console.log('\uD83D\uDD04 [OpenFront Channel] - Has access_token:', !!tokenData.access_token);\n console.log('\uD83D\uDD04 [OpenFront Channel] - Has refresh_token:', !!tokenData.refresh_token);\n console.log('\uD83D\uDD04 [OpenFront Channel] - Expires in:', tokenData.expires_in, 'seconds');\n \n const { access_token, refresh_token, expires_in } = tokenData;\n \n // Update stored access token and expiry in database\n console.log('\uD83D\uDD04 [OpenFront Channel] Updating tokens in database...');\n try {\n console.log('\uD83D\uDD04 [OpenFront Channel] Updating channel:', channel.id);\n await keystoneContext.sudo().query.Channel.updateOne({\n where: { id: channel.id },\n data: {\n accessToken: access_token,\n ...(refresh_token && { refreshToken: refresh_token }),\n ...(expires_in && { tokenExpiresAt: new Date(Date.now() + (expires_in * 1000)) })\n }\n });\n console.log('\u2705 [OpenFront Channel] Channel updated with new tokens:', channel.id);\n } catch (error) {\n console.error('\uD83D\uDEA8 [OpenFront Channel] Failed to update channel tokens in database:', error);\n // Continue with the request even if database update fails\n }\n \n console.log('\u2705 [OpenFront Channel] Returning fresh access token');\n return access_token;\n } else {\n // Token hasn't expired yet, use existing one\n console.log('\u2705 [OpenFront Channel] Token still valid, using existing access token');\n return platform.accessToken;\n }\n }\n \n // If no refresh token, just use the access token as-is\n console.log('\u26A0\uFE0F [OpenFront Channel] No refresh token available, using existing access token');\n return platform.accessToken;\n};\n\n// Helper function to create OpenFront GraphQL client with fresh token\nconst createOpenFrontClient = async (platform: OpenFrontPlatform) => {\n const freshAccessToken = await getFreshAccessToken(platform);\n\n return new GraphQLClient(\n `${platform.domain}/api/graphql`,\n {\n headers: {\n \"Authorization\": `Bearer ${freshAccessToken}`,\n \"Content-Type\": \"application/json\",\n },\n }\n );\n};\n\n// Helper function to get product image URL\n// imagePath is a relative path (e.g., \"/images/product.jpg\") that needs domain prepended\n// image.url is an absolute S3 URL that can be used directly\nconst getProductImageUrl = (productImage: any, domain: string): string | null => {\n if (productImage?.imagePath) {\n return `${domain}${productImage.imagePath}`;\n }\n return productImage?.image?.url || null;\n};\n\n// Function to search products for fulfillment\nexport async function searchProductsFunction({ \n platform, \n searchEntry, \n after \n}: { \n platform: OpenFrontPlatform; \n searchEntry: string; \n after?: string; \n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const gqlQuery = gql`\n query SearchChannelProducts($where: ProductWhereInput, $take: Int, $skip: Int) {\n products(where: $where, take: $take, skip: $skip, orderBy: { createdAt: desc }) {\n id\n title\n handle\n productImages {\n image {\n url\n }\n imagePath\n }\n productVariants {\n id\n title\n sku\n inventoryQuantity\n prices {\n id\n amount\n currency {\n code\n }\n }\n }\n status\n }\n productsCount(where: $where)\n }\n `;\n\n // Build search filter - only show products available for fulfillment\n const where: any = {\n status: { equals: \"published\" },\n productVariants: {\n some: {\n inventoryQuantity: { gt: 0 } // Only products with inventory\n }\n }\n };\n\n if (searchEntry && searchEntry.trim()) {\n where.OR = [\n { title: { contains: searchEntry, mode: \"insensitive\" } },\n { handle: { contains: searchEntry, mode: \"insensitive\" } },\n { productVariants: { some: { sku: { contains: searchEntry, mode: \"insensitive\" } } } }\n ];\n }\n\n // Handle pagination\n const take = 15;\n const skip = after ? parseInt(Buffer.from(after, 'base64').toString()) : 0;\n\n const { products, productsCount } = await openFrontClient.request(gqlQuery, {\n where,\n take,\n skip,\n }) as any;\n\n if (!products || products.length === 0) {\n throw new Error(\"No fulfillment products found from OpenFront\");\n }\n\n // Transform products to Openship channel format\n const transformedProducts = products.flatMap((product: any) => \n product.productVariants\n .filter((variant: any) => variant.inventoryQuantity > 0) // Only variants with inventory\n .map((variant: any) => {\n const firstPrice = variant.prices[0];\n const firstImage = product.productImages[0];\n \n return {\n image: getProductImageUrl(firstImage, platform.domain),\n title: `${product.title} - ${variant.title}`,\n productId: product.id,\n variantId: variant.id,\n price: firstPrice ? (firstPrice.amount / 100).toFixed(2) : \"0.00\", // Convert from cents\n availableForSale: true, // Already filtered above\n inventory: variant.inventoryQuantity,\n inventoryTracked: true,\n productLink: `https://${platform.domain}/products/${product.handle}`,\n cursor: Buffer.from((skip + products.indexOf(product) + 1).toString()).toString('base64'),\n };\n })\n );\n\n const hasNextPage = skip + take < productsCount;\n const endCursor = hasNextPage ? Buffer.from((skip + take).toString()).toString('base64') : null;\n\n return { \n products: transformedProducts, \n pageInfo: {\n hasNextPage,\n endCursor\n }\n };\n}\n\n// Function to get a specific product for fulfillment\nexport async function getProductFunction({\n platform,\n productId,\n variantId,\n}: {\n platform: OpenFrontPlatform;\n productId: string;\n variantId?: string;\n}) {\n console.log(\"OpenFront Channel getProductFunction called with:\", { platform: platform.domain, productId, variantId });\n \n const openFrontClient = await createOpenFrontClient(platform);\n\n const gqlQuery = gql`\n query GetChannelProduct($productId: ID!, $variantWhere: ProductVariantWhereInput) {\n product(where: { id: $productId }) {\n id\n title\n handle\n productImages {\n image {\n url\n }\n imagePath\n }\n productVariants(where: $variantWhere) {\n id\n title\n sku\n inventoryQuantity\n prices {\n id\n amount\n currency {\n code\n }\n }\n }\n status\n }\n }\n `;\n\n const { product } = await openFrontClient.request(gqlQuery, {\n productId,\n variantWhere: variantId ? { id: { equals: variantId } } : {},\n }) as any;\n\n if (!product || product.status !== \"published\") {\n throw new Error(\"Product not available for fulfillment from OpenFront\");\n }\n\n const variant = variantId \n ? product.productVariants.find((v: any) => v.id === variantId)\n : product.productVariants[0];\n\n if (!variant || variant.inventoryQuantity <= 0) {\n throw new Error(\"Product variant not available for fulfillment from OpenFront\");\n }\n\n const firstPrice = variant.prices[0];\n const firstImage = product.productImages[0];\n\n const transformedProduct = {\n image: getProductImageUrl(firstImage, platform.domain),\n title: `${product.title} - ${variant.title}`,\n productId: product.id,\n variantId: variant.id,\n price: firstPrice ? (firstPrice.amount / 100).toFixed(2) : \"0.00\",\n availableForSale: true,\n inventory: variant.inventoryQuantity,\n inventoryTracked: true,\n productLink: `https://${platform.domain}/products/${product.handle}`,\n };\n\n return { product: transformedProduct };\n}\n\n// Function to create a purchase order (fulfillment order)\nexport async function createPurchaseFunction({\n platform,\n cartItems,\n shipping,\n}: {\n platform: OpenFrontPlatform;\n cartItems: any[];\n shipping: any;\n notes?: string;\n}) {\n console.log(`\uD83D\uDED2 OpenFront Channel: Creating purchase with ${cartItems.length} items`);\n console.log(`\uD83D\uDE9A OpenFront Channel: Ship to: ${shipping?.firstName} ${shipping?.lastName}`);\n console.log(`\uD83D\uDCE6 OpenFront Channel: Full shipping data:`, JSON.stringify(shipping, null, 2));\n console.log(`\uD83D\uDCE6 OpenFront Channel: Platform data:`, JSON.stringify(platform, null, 2));\n console.log(`\uD83D\uDCE6 OpenFront Channel: Cart items:`, JSON.stringify(cartItems, null, 2));\n\n const openFrontClient = await createOpenFrontClient(platform);\n\n try {\n // Step 1: Get region data with currency ID and taxRate (like storefront does)\n const currencyCode = (shipping?.currency || \"USD\").toLowerCase();\n const getRegionQuery = gql`\n query GetRegion($currencyCode: String!) {\n regions(where: { currency: { code: { equals: $currencyCode } } }) {\n id\n taxRate\n currency {\n id\n code\n }\n }\n }\n `;\n \n const { regions } = await openFrontClient.request(getRegionQuery, {\n currencyCode: currencyCode,\n }) as any;\n \n const region = regions[0];\n if (!region) {\n throw new Error(`No region found for currency: ${currencyCode}`);\n }\n\n // Step 2: Create cart (following storefront flow)\n console.log(\"\uD83D\uDED2 [OpenFront Channel] Creating cart with region:\", region.id);\n \n const { createCart: cart } = await openFrontClient.request(gql`\n mutation CreateCart($data: CartCreateInput!) {\n createCart(data: $data) {\n id\n region {\n id\n currency {\n id\n code\n }\n }\n }\n }\n `, {\n data: {\n region: { connect: { id: region.id } },\n email: shipping?.email || `order-${Date.now()}@openship.generated`\n }\n }) as any;\n\n console.log(\"\u2705 [OpenFront Channel] Cart created with ID:\", cart.id);\n\n // Step 3: Add line items to cart (this computes unitPrice/total automatically)\n const lineItemsToCreate = [];\n for (const item of cartItems) {\n lineItemsToCreate.push({\n productVariant: { connect: { id: item.variantId } },\n quantity: item.quantity\n });\n }\n\n console.log(\"\uD83D\uDCE6 [OpenFront Channel] Adding\", lineItemsToCreate.length, \"line items to cart\");\n\n await openFrontClient.request(gql`\n mutation AddLineItemsToCart($cartId: ID!, $data: CartUpdateInput!) {\n updateActiveCart(cartId: $cartId, data: $data) {\n id\n }\n }\n `, {\n cartId: cart.id,\n data: {\n lineItems: {\n create: lineItemsToCreate\n }\n }\n }) as any;\n\n console.log(\"\u2705 [OpenFront Channel] Line items added to cart\");\n\n // Step 4: Create addresses and add to cart\n console.log(\"\uD83D\uDCCD [OpenFront Channel] Creating shipping address\");\n \n const { createAddress: shippingAddr } = await openFrontClient.request(gql`\n mutation CreateAddress($data: AddressCreateInput!) {\n createAddress(data: $data) {\n id\n }\n }\n `, {\n data: {\n firstName: shipping?.firstName || \"Guest\",\n lastName: shipping?.lastName || \"Customer\", \n address1: shipping?.address1 || \"123 Default St\",\n city: shipping?.city || \"Default City\",\n province: shipping?.state || \"NY\",\n postalCode: shipping?.zip || \"10001\",\n phone: shipping?.phone || \"\",\n country: {\n connect: {\n iso2: (shipping?.country || \"US\").toLowerCase()\n }\n }\n }\n }) as any;\n\n console.log(\"\u2705 [OpenFront Channel] Shipping address created:\", shippingAddr.id);\n\n // Step 5: Update cart with addresses\n await openFrontClient.request(gql`\n mutation UpdateCartAddresses($cartId: ID!, $data: CartUpdateInput!) {\n updateActiveCart(cartId: $cartId, data: $data) {\n id\n }\n }\n `, {\n cartId: cart.id,\n data: {\n shippingAddress: { connect: { id: shippingAddr.id } },\n billingAddress: { connect: { id: shippingAddr.id } }\n }\n }) as any;\n\n console.log(\"\u2705 [OpenFront Channel] Cart updated with addresses\");\n\n // Step 6: Complete cart to create order (like storefront placeOrder)\n console.log(\"\uD83C\uDFAF [OpenFront Channel] Completing cart to create order\");\n \n console.log(\"\uD83C\uDFAF [OpenFront Channel] Calling completeActiveCart for cart:\", cart.id);\n \n const completeResult = await openFrontClient.request(gql`\n mutation CompleteActiveCart($cartId: ID!) {\n completeActiveCart(cartId: $cartId)\n }\n `, {\n cartId: cart.id\n }) as any;\n\n console.log(\"\uD83D\uDD0D [OpenFront Channel] completeActiveCart result:\", JSON.stringify(completeResult, null, 2));\n\n const order = completeResult.completeActiveCart;\n if (!order?.id) {\n throw new Error(\"Failed to complete cart - no order created\");\n }\n\n console.log(\"\uD83D\uDD0D [OpenFront Channel] COMPLETE ORDER RESULT:\", JSON.stringify(order, null, 2));\n console.log(\"\uD83C\uDF89 [OpenFront Channel] Order created successfully:\", order.id);\n\n // Process line items from cart items (since order doesn't include line items)\n const processedLineItems = cartItems.map((item: any) => ({\n id: item.variantId,\n title: item.name || `Product ${item.variantId}`,\n quantity: item.quantity,\n variantId: item.variantId,\n }));\n\n // Return in the same format as Shopify channel\n return {\n purchaseId: order.id,\n orderNumber: `#${order.displayId}`,\n totalPrice: order.total,\n invoiceUrl: `https://${platform.domain}/admin/orders/${order.id}`,\n lineItems: processedLineItems,\n status: \"pending\",\n };\n\n } catch (error: any) {\n console.error('\uD83D\uDEA8 OpenFront Channel: Purchase creation failed:', error);\n \n if (error.response?.errors) {\n console.error('\uD83D\uDEA8 GraphQL Errors:');\n error.response.errors.forEach((err: any, i: number) => {\n console.error(` ${i + 1}. ${err.message}`);\n if (err.path) {\n console.error(` Path: ${err.path.join(' -> ')}`);\n }\n if (err.extensions) {\n console.error(` Extensions:`, err.extensions);\n }\n });\n }\n \n // Return error response with detailed error info\n return {\n purchaseId: null,\n orderNumber: null,\n totalPrice: \"0.00\",\n invoiceUrl: null,\n lineItems: cartItems.map((item: any) => ({\n id: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,\n title: item.name || `Product ${item.variantId}`,\n quantity: item.quantity,\n variantId: item.variantId,\n productId: item.productId\n })),\n status: \"error\",\n error: error instanceof Error ? error.message : \"Unknown error\"\n };\n }\n}\n\n// Function to create webhook for channel events - simplified to update user's webhook URL\nexport async function createWebhookFunction({\n platform,\n endpoint,\n events,\n}: {\n platform: OpenFrontPlatform;\n endpoint: string;\n events: string[];\n}) {\n console.log('\uD83E\uDE9D [OpenFront Channel] createWebhookFunction called');\n console.log('\uD83E\uDE9D [OpenFront Channel] Platform domain:', platform.domain);\n console.log('\uD83E\uDE9D [OpenFront Channel] Endpoint URL:', endpoint);\n console.log('\uD83E\uDE9D [OpenFront Channel] Events received:', events);\n console.log('\uD83E\uDE9D [OpenFront Channel] Events type:', typeof events, 'Array?', Array.isArray(events));\n console.log('\uD83E\uDE9D [OpenFront Channel] Platform data:', JSON.stringify(platform, null, 2));\n\n // Map Openship channel events to OpenFront events\n const eventMap: Record = {\n ORDER_CREATED: \"order.created\",\n ORDER_CANCELLED: \"order.cancelled\", \n TRACKING_CREATED: \"fulfillment.created\",\n };\n\n const openFrontEvents = events.map(event => {\n const mapped = eventMap[event] || event;\n console.log(`\uD83E\uDE9D [OpenFront Channel] Mapping: ${event} -> ${mapped}`);\n return mapped;\n });\n console.log('\uD83E\uDE9D [OpenFront Channel] Final mapped events array:', openFrontEvents);\n console.log('\uD83E\uDE9D [OpenFront Channel] Joined events string:', openFrontEvents.join(\", \"));\n\n try {\n console.log('\uD83E\uDE9D [OpenFront Channel] Creating OpenFront GraphQL client...');\n const openFrontClient = await createOpenFrontClient(platform);\n console.log('\u2705 [OpenFront Channel] GraphQL client created successfully');\n\n // Get current user from the access token\n console.log('\uD83E\uDE9D [OpenFront Channel] Fetching current user...');\n const getUserQuery = gql`\n query GetCurrentUser {\n authenticatedItem {\n ... on User {\n id\n email\n orderWebhookUrl\n }\n }\n }\n `;\n\n console.log('\uD83E\uDE9D [OpenFront Channel] Executing getUserQuery...');\n const { authenticatedItem: user } = await openFrontClient.request(getUserQuery) as any;\n console.log('\uD83E\uDE9D [OpenFront Channel] getUserQuery result:', JSON.stringify(user, null, 2));\n \n if (!user) {\n console.error('\uD83D\uDEA8 [OpenFront Channel] User not authenticated - authenticatedItem is null/undefined');\n throw new Error('User not authenticated');\n }\n\n console.log('\u2705 [OpenFront Channel] User authenticated successfully');\n console.log('\uD83E\uDE9D [OpenFront Channel] User ID:', user.id);\n console.log('\uD83E\uDE9D [OpenFront Channel] User email:', user.email);\n console.log('\uD83E\uDE9D [OpenFront Channel] Current webhook URL:', user.orderWebhookUrl);\n\n // Update the user's webhook URL using updateActiveUser (bypasses access restrictions)\n console.log('\uD83E\uDE9D [OpenFront Channel] Updating user webhook URL...');\n const updateUserMutation = gql`\n mutation UpdateActiveUserWebhookUrl($data: UserUpdateProfileInput!) {\n updateActiveUser(data: $data) {\n id\n orderWebhookUrl\n }\n }\n `;\n\n console.log('\uD83E\uDE9D [OpenFront Channel] Update mutation variables:');\n console.log('\uD83E\uDE9D [OpenFront Channel] - User ID:', user.id);\n console.log('\uD83E\uDE9D [OpenFront Channel] - New webhook URL:', endpoint);\n\n const result = await openFrontClient.request(updateUserMutation, {\n data: { orderWebhookUrl: endpoint }\n }) as any;\n\n console.log('\uD83E\uDE9D [OpenFront Channel] Update mutation result:', JSON.stringify(result, null, 2));\n\n const updatedUser = result.updateActiveUser;\n console.log('\u2705 [OpenFront Channel] User webhook URL updated successfully');\n console.log('\uD83E\uDE9D [OpenFront Channel] Updated user ID:', updatedUser.id);\n console.log('\uD83E\uDE9D [OpenFront Channel] Updated webhook URL:', updatedUser.orderWebhookUrl);\n\n const webhookResponse = { \n webhooks: [{ \n id: `user-${updatedUser.id}`,\n callbackUrl: updatedUser.orderWebhookUrl,\n topic: openFrontEvents.join(\", \"), // Join array into comma-separated string\n format: \"JSON\",\n createdAt: new Date().toISOString()\n }], \n webhookId: `user-${updatedUser.id}`\n };\n\n console.log('\uD83E\uDE9D [OpenFront Channel] Final webhook response:', JSON.stringify(webhookResponse, null, 2));\n return webhookResponse;\n\n } catch (error: any) {\n console.error('\uD83D\uDEA8 [OpenFront Channel] createWebhookFunction failed:', error);\n console.error('\uD83D\uDEA8 [OpenFront Channel] Error message:', error.message);\n console.error('\uD83D\uDEA8 [OpenFront Channel] Error stack:', error.stack);\n \n if (error.response) {\n console.error('\uD83D\uDEA8 [OpenFront Channel] GraphQL response:', JSON.stringify(error.response, null, 2));\n \n if (error.response.errors) {\n console.error('\uD83D\uDEA8 [OpenFront Channel] GraphQL errors:');\n error.response.errors.forEach((err: any, i: number) => {\n console.error(`\uD83D\uDEA8 [OpenFront Channel] ${i + 1}. ${err.message}`);\n if (err.path) {\n console.error(`\uD83D\uDEA8 [OpenFront Channel] Path: ${err.path.join(' -> ')}`);\n }\n if (err.extensions) {\n console.error(`\uD83D\uDEA8 [OpenFront Channel] Extensions:`, err.extensions);\n }\n });\n }\n }\n \n throw error;\n }\n}\n\n// Function to delete webhook - clear user's webhook URL\nexport async function deleteWebhookFunction({\n platform,\n webhookId,\n}: {\n platform: OpenFrontPlatform;\n webhookId: string;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n // Extract user ID from webhookId (format: \"user-{userId}\")\n const userId = webhookId.replace('user-', '');\n\n // Clear the user's webhook URL\n const updateUserMutation = gql`\n mutation ClearUserWebhookUrl($where: UserWhereUniqueInput!, $data: UserUpdateInput!) {\n updateUser(where: $where, data: $data) {\n id\n orderWebhookUrl\n }\n }\n `;\n\n const result = await openFrontClient.request(updateUserMutation, {\n where: { id: userId },\n data: { orderWebhookUrl: null }\n });\n\n return result;\n}\n\n// Function to get webhooks - get user's webhook URL \nexport async function getWebhooksFunction({\n platform,\n}: {\n platform: OpenFrontPlatform;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n // Map OpenFront events back to Openship channel events\n const eventMap: Record = {\n \"order.created\": \"PURCHASE_CREATED\",\n \"fulfillment.created\": \"PURCHASE_SHIPPED\",\n };\n\n // Get current user's webhook URL\n const getUserQuery = gql`\n query GetCurrentUser {\n authenticatedItem {\n ... on User {\n id\n email\n orderWebhookUrl\n createdAt\n }\n }\n }\n `;\n\n const { authenticatedItem: user } = await openFrontClient.request(getUserQuery) as any;\n \n if (!user || !user.orderWebhookUrl) {\n return { webhooks: [] };\n }\n\n // For OpenFront channels, we support both PURCHASE_CREATED and PURCHASE_SHIPPED\n // Since we store a single webhook URL on the user, we return both events as supported\n const webhooks = [{\n id: `user-${user.id}`,\n callbackUrl: user.orderWebhookUrl,\n topic: [\"PURCHASE_CREATED\", \"PURCHASE_SHIPPED\"], // These are the channel events we support\n format: \"JSON\",\n createdAt: user.createdAt\n }];\n\n return { webhooks };\n}\n\n// Function to handle purchase tracking updates\nexport async function addTrackingFunction({\n platform,\n purchaseId,\n trackingCompany,\n trackingNumber,\n}: {\n platform: OpenFrontPlatform;\n purchaseId: string;\n trackingCompany: string;\n trackingNumber: string;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n // Update fulfillment order with tracking information\n const updateTrackingMutation = gql`\n mutation UpdateOrderTracking($where: OrderWhereUniqueInput!, $data: OrderUpdateInput!) {\n updateOrder(where: $where, data: $data) {\n id\n orderNumber\n status\n }\n }\n `;\n\n // Create or update fulfillment record\n const createFulfillmentMutation = gql`\n mutation CreateOrderFulfillment($data: FulfillmentCreateInput!) {\n createFulfillment(data: $data) {\n id\n trackingNumber\n trackingCompany\n status\n }\n }\n `;\n\n try {\n // Create fulfillment record\n const fulfillmentResult = await openFrontClient.request(createFulfillmentMutation, {\n data: {\n order: { connect: { id: purchaseId } },\n trackingNumber,\n trackingCompany,\n status: \"shipped\"\n },\n });\n\n // Update order status\n await openFrontClient.request(updateTrackingMutation, {\n where: { id: purchaseId },\n data: { status: \"shipped\" },\n });\n\n console.log(`\uD83D\uDCE6 OpenFront Channel: Tracking added for order ${purchaseId}: ${trackingCompany} ${trackingNumber}`);\n\n return fulfillmentResult;\n } catch (error) {\n console.error('OpenFront Channel: Failed to add tracking:', error);\n throw error;\n }\n}\n\n// Webhook handler for fulfillment updates\nexport async function fulfillmentUpdateWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: OpenFrontPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const signature = headers[\"x-openfront-webhook-signature\"];\n if (!signature) {\n throw new Error(\"Missing webhook signature\");\n }\n\n const fulfillmentData = event.data;\n \n return {\n purchaseId: fulfillmentData.order?.id,\n trackingNumber: fulfillmentData.trackingNumber,\n trackingCompany: fulfillmentData.trackingCompany,\n status: fulfillmentData.status,\n type: \"fulfillment_update\"\n };\n}\n\nexport async function oAuthFunction({\n platform,\n callbackUrl,\n}: {\n platform: OpenFrontPlatform;\n callbackUrl: string;\n}) {\n if (!platform.appKey) {\n throw new Error(\"OpenFront OAuth requires appKey in platform configuration\");\n }\n \n // Generate OpenFront OAuth URL for channel installation\n const scopes = \"read_products,write_products,read_orders,write_orders,read_fulfillments,write_fulfillments,read_webhooks,write_webhooks\";\n const state = (platform as any).state || Math.random().toString(36).substring(7);\n \n // Redirect to apps page with install popup (same as shop integration)\n const openFrontAuthUrl = `${platform.domain}/dashboard/platform/apps?` +\n `install=true&` +\n `client_id=${platform.appKey}&` +\n `scope=${encodeURIComponent(scopes)}&` +\n `redirect_uri=${encodeURIComponent(callbackUrl)}&` +\n `state=${state}&` +\n `response_type=code`;\n \n return { authUrl: openFrontAuthUrl };\n}\n\nexport async function oAuthCallbackFunction({\n platform,\n code,\n shop,\n state,\n appKey,\n appSecret,\n redirectUri,\n}: {\n platform: OpenFrontPlatform;\n code: string;\n shop: string;\n state: string;\n appKey?: string;\n appSecret?: string;\n redirectUri?: string;\n}) {\n // Use platform domain or shop parameter\n const domain = platform.domain || shop;\n const tokenUrl = `${domain}/api/oauth/token`;\n \n // Use passed credentials first (for flexibility), then platform's credentials\n const clientId = appKey || platform.appKey;\n const clientSecret = appSecret || platform.appSecret;\n \n if (!clientId || !clientSecret) {\n throw new Error(\"OpenFront OAuth requires appKey and appSecret in platform configuration or as parameters\");\n }\n \n const formData = new URLSearchParams({\n grant_type: \"authorization_code\",\n client_id: clientId,\n client_secret: clientSecret,\n code,\n redirect_uri: redirectUri || \"\",\n });\n\n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: formData,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error(\"OpenFront OAuth error:\", errorText);\n throw new Error(`Failed to exchange OAuth code for access token: ${response.statusText}`);\n }\n\n const { access_token, refresh_token, expires_in } = await response.json();\n \n // Return OAuth response with refresh token support\n return {\n accessToken: access_token,\n refreshToken: refresh_token,\n expiresIn: expires_in,\n tokenExpiresAt: new Date(Date.now() + (expires_in * 1000)).toISOString()\n };\n}\n\n// Required OAuth scopes for OpenFront channel integration\nconst REQUIRED_SCOPES = \"read_products,write_products,read_orders,write_orders,read_fulfillments,write_fulfillments,read_webhooks,write_webhooks\";\n\nexport function scopes() {\n return REQUIRED_SCOPES;\n}", "import { GraphQLClient, gql } from \"graphql-request\";\n\ninterface ShopifyPlatform {\n domain: string;\n accessToken: string;\n appKey?: string;\n appSecret?: string;\n}\n\ninterface SearchProductsArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface GetProductArgs {\n productId: string;\n variantId?: string;\n}\n\ninterface CreatePurchaseArgs {\n cartItems: Array<{\n variantId: string;\n quantity: number;\n price?: string;\n }>;\n shipping?: {\n firstName: string;\n lastName: string;\n address1: string;\n address2?: string;\n city: string;\n province: string;\n country: string;\n zip: string;\n phone?: string;\n };\n notes?: string;\n}\n\ninterface CreateWebhookArgs {\n endpoint: string;\n events: string[];\n}\n\ninterface DeleteWebhookArgs {\n webhookId: string;\n}\n\ninterface OAuthArgs {\n callbackUrl: string;\n}\n\ninterface OAuthCallbackArgs {\n code: string;\n shop: string;\n state: string;\n}\n\ninterface WebhookEventArgs {\n event: any;\n headers: Record;\n}\n\n// Function to search products for purchasing\nexport async function searchProductsFunction({ \n platform, \n searchEntry, \n after \n}: { \n platform: ShopifyPlatform; \n searchEntry: string; \n after?: string; \n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const gqlQuery = gql`\n query SearchProducts($query: String, $after: String) {\n productVariants(first: 15, query: $query, after: $after) {\n edges {\n node {\n id\n availableForSale\n image {\n originalSrc\n }\n price\n title\n product {\n id\n handle\n title\n images(first: 1) {\n edges {\n node {\n originalSrc\n }\n }\n }\n }\n inventoryQuantity\n inventoryPolicy\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n `;\n\n const result = await shopifyClient.request(gqlQuery, {\n query: searchEntry,\n after,\n }) as any;\n const { productVariants } = result;\n\n if (productVariants.edges.length < 1) {\n throw new Error(\"No products found from Shopify channel\");\n }\n\n const products = productVariants.edges.map(({ node, cursor }: any) => ({\n image:\n node.image?.originalSrc || node.product.images.edges[0]?.node.originalSrc,\n title: `${node.product.title} - ${node.title}`,\n productId: node.product.id.split(\"/\").pop(),\n variantId: node.id.split(\"/\").pop(),\n price: node.price,\n availableForSale: node.availableForSale,\n inventory: node.inventoryQuantity,\n inventoryTracked: node.inventoryPolicy !== \"deny\",\n productLink: `https://${platform.domain}/products/${node.product.handle}`,\n cursor,\n }));\n\n return { \n products, \n pageInfo: productVariants.pageInfo \n };\n}\n\n// Function to get a specific product by variantId and productId\nexport async function getProductFunction({\n platform,\n productId,\n variantId,\n}: {\n platform: ShopifyPlatform;\n productId: string;\n variantId?: string;\n}) {\n console.log(\"CHANNEL getProductFunction called with:\", { platform: platform.domain, productId, variantId });\n \n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const gqlQuery = gql`\n query GetProduct($variantId: ID!) {\n productVariant(id: $variantId) {\n id\n availableForSale\n image {\n originalSrc\n }\n price\n title\n product {\n id\n handle\n title\n images(first: 1) {\n edges {\n node {\n originalSrc\n }\n }\n }\n }\n inventoryQuantity\n inventoryPolicy\n }\n }\n `;\n\n const fullVariantId = `gid://shopify/ProductVariant/${variantId}`;\n console.log(\"CHANNEL querying with variantId:\", fullVariantId);\n \n const variantResult = await shopifyClient.request(gqlQuery, {\n variantId: fullVariantId,\n }) as any;\n const { productVariant } = variantResult;\n\n console.log(\"CHANNEL productVariant result:\", productVariant);\n\n if (!productVariant) {\n throw new Error(\"Product not found from Shopify channel\");\n }\n\n const product = {\n image:\n productVariant.image?.originalSrc ||\n productVariant.product.images.edges[0]?.node.originalSrc,\n title: `${productVariant.product.title} - ${productVariant.title}`,\n productId: productVariant.product.id.split(\"/\").pop(),\n variantId: productVariant.id.split(\"/\").pop(),\n price: productVariant.price,\n availableForSale: productVariant.availableForSale,\n inventory: productVariant.inventoryQuantity,\n inventoryTracked: productVariant.inventoryPolicy !== \"deny\",\n productLink: `https://${platform.domain}/products/${productVariant.product.handle}`,\n };\n\n return { product };\n}\n\nexport async function createPurchaseFunction({\n platform,\n cartItems,\n shipping,\n notes,\n}: {\n platform: ShopifyPlatform;\n cartItems: CreatePurchaseArgs['cartItems'];\n shipping?: CreatePurchaseArgs['shipping'];\n notes?: string;\n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const mutation = gql`\n mutation CreateDraftOrder($input: DraftOrderInput!) {\n draftOrderCreate(input: $input) {\n draftOrder {\n id\n name\n invoiceUrl\n totalPrice\n lineItems(first: 50) {\n edges {\n node {\n id\n title\n quantity\n originalUnitPrice\n variant {\n id\n title\n product {\n id\n title\n }\n }\n }\n }\n }\n shippingAddress {\n firstName\n lastName\n address1\n address2\n city\n province\n country\n zip\n phone\n }\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const lineItems = cartItems.map(item => ({\n variantId: `gid://shopify/ProductVariant/${item.variantId}`,\n quantity: item.quantity,\n originalUnitPrice: item.price,\n }));\n\n const input: any = {\n lineItems,\n note: notes,\n };\n\n if (shipping) {\n input.shippingAddress = {\n firstName: shipping.firstName,\n lastName: shipping.lastName,\n address1: shipping.address1,\n address2: shipping.address2,\n city: shipping.city,\n province: shipping.province,\n country: shipping.country,\n zip: shipping.zip,\n phone: shipping.phone,\n };\n }\n\n const result = await shopifyClient.request(mutation, { input }) as any;\n\n if (result.draftOrderCreate.userErrors.length > 0) {\n throw new Error(`Failed to create purchase: ${result.draftOrderCreate.userErrors.map((e: any) => e.message).join(', ')}`);\n }\n\n const draftOrder = result.draftOrderCreate.draftOrder;\n\n // Complete the draft order to create an actual order\n const completeMutation = gql`\n mutation CompleteDraftOrder($id: ID!) {\n draftOrderComplete(id: $id) {\n draftOrder {\n id\n order {\n id\n name\n totalPrice\n lineItems(first: 50) {\n edges {\n node {\n id\n title\n quantity\n variant {\n id\n }\n }\n }\n }\n }\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const completeResult = await shopifyClient.request(completeMutation, {\n id: draftOrder.id,\n }) as any;\n\n if (completeResult.draftOrderComplete.userErrors.length > 0) {\n throw new Error(`Failed to complete purchase: ${completeResult.draftOrderComplete.userErrors.map((e: any) => e.message).join(', ')}`);\n }\n\n const order = completeResult.draftOrderComplete.draftOrder.order;\n\n return {\n purchaseId: order.id.split(\"/\").pop(),\n orderNumber: order.name,\n totalPrice: order.totalPrice,\n invoiceUrl: draftOrder.invoiceUrl,\n lineItems: order.lineItems.edges.map(({ node }: any) => ({\n id: node.id.split(\"/\").pop(),\n title: node.title,\n quantity: node.quantity,\n variantId: node.variant.id.split(\"/\").pop(),\n })),\n status: \"pending\",\n };\n}\n\nexport async function createWebhookFunction({\n platform,\n endpoint,\n events,\n}: {\n platform: ShopifyPlatform;\n endpoint: string;\n events: string[];\n}) {\n const mapTopic: Record = {\n ORDER_CREATED: \"ORDERS_CREATE\",\n ORDER_CANCELLED: \"ORDERS_CANCELLED\",\n ORDER_CHARGEBACKED: \"DISPUTES_CREATE\",\n TRACKING_CREATED: \"FULFILLMENTS_CREATE\",\n };\n\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const webhooks = [];\n\n for (const event of events) {\n const shopifyTopic = mapTopic[event] || event;\n const mutation = gql`\n mutation webhookSubscriptionCreate($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) {\n webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) {\n webhookSubscription {\n id\n endpoint {\n __typename\n ... on WebhookHttpEndpoint {\n callbackUrl\n }\n }\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const result = await shopifyClient.request(mutation, {\n topic: shopifyTopic.toUpperCase(),\n webhookSubscription: {\n callbackUrl: endpoint,\n format: \"JSON\",\n },\n }) as any;\n\n webhooks.push(result.webhookSubscriptionCreate.webhookSubscription);\n }\n\n return { webhooks };\n}\n\nexport async function deleteWebhookFunction({\n platform,\n webhookId,\n}: {\n platform: ShopifyPlatform;\n webhookId: string;\n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const mutation = gql`\n mutation DeleteWebhook($id: ID!) {\n webhookSubscriptionDelete(id: $id) {\n deletedWebhookSubscriptionId\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const result = await shopifyClient.request(mutation, {\n id: `gid://shopify/WebhookSubscription/${webhookId}`,\n }) as any;\n\n return (result as any).webhookSubscriptionDelete;\n}\n\nexport async function getWebhooksFunction({\n platform,\n}: {\n platform: ShopifyPlatform;\n}) {\n const mapTopic = {\n ORDERS_CREATE: \"ORDER_CREATED\",\n ORDERS_CANCELLED: \"ORDER_CANCELLED\",\n DISPUTES_CREATE: \"ORDER_CHARGEBACKED\",\n FULFILLMENTS_CREATE: \"TRACKING_CREATED\",\n };\n\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const query = gql`\n query GetWebhooks {\n webhookSubscriptions(first: 50) {\n edges {\n node {\n id\n topic\n format\n createdAt\n endpoint {\n __typename\n ... on WebhookHttpEndpoint {\n callbackUrl\n }\n }\n }\n }\n }\n }\n `;\n\n const webhooksResult = await shopifyClient.request(query) as any;\n const { webhookSubscriptions } = webhooksResult;\n\n const webhooks = webhookSubscriptions.edges.map(({ node }: any) => ({\n id: node.id.split(\"/\").pop(),\n callbackUrl: node.endpoint.callbackUrl,\n topic: (mapTopic as any)[node.topic] || node.topic,\n format: node.format,\n createdAt: node.createdAt,\n }));\n\n return { webhooks };\n}\n\nexport async function oAuthFunction({\n platform,\n callbackUrl,\n}: {\n platform: ShopifyPlatform;\n callbackUrl: string;\n}) {\n // Use platform's appKey if available, otherwise fall back to env variable for backward compatibility\n const clientId = platform.appKey || process.env.SHOPIFY_APP_KEY;\n \n if (!clientId) {\n throw new Error(\"Shopify OAuth requires appKey in platform config or SHOPIFY_APP_KEY environment variable\");\n }\n \n const scopes = \"read_products,write_products,read_orders,write_orders,read_inventory,write_inventory\";\n const shopifyAuthUrl = `https://${platform.domain}/admin/oauth/authorize?client_id=${clientId}&scope=${scopes}&redirect_uri=${callbackUrl}&state=${Math.random().toString(36).substring(7)}`;\n \n return { authUrl: shopifyAuthUrl };\n}\n\nexport async function oAuthCallbackFunction({\n platform,\n code,\n shop,\n state,\n}: {\n platform: ShopifyPlatform;\n code: string;\n shop: string;\n state: string;\n}) {\n // Use platform credentials if available, otherwise fall back to env variables for backward compatibility\n const clientId = platform.appKey || process.env.SHOPIFY_APP_KEY;\n const clientSecret = platform.appSecret || process.env.SHOPIFY_APP_SECRET;\n \n if (!clientId || !clientSecret) {\n throw new Error(\"Shopify OAuth requires appKey and appSecret in platform config or environment variables\");\n }\n \n const tokenUrl = `https://${shop}/admin/oauth/access_token`;\n \n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n client_id: clientId,\n client_secret: clientSecret,\n code,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\"Failed to exchange OAuth code for access token\");\n }\n\n const { access_token } = await response.json();\n \n return { \n accessToken: access_token,\n domain: shop,\n };\n}\n\nexport async function createTrackingWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: ShopifyPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const hmac = headers[\"x-shopify-hmac-sha256\"];\n if (!hmac) {\n throw new Error(\"Missing webhook HMAC\");\n }\n\n // Process the fulfillment data\n const fulfillment = {\n id: event.id,\n orderId: event.order_id,\n status: event.status,\n trackingCompany: event.tracking_company,\n trackingNumber: event.tracking_number,\n trackingUrl: event.tracking_url,\n purchaseId: event.order_id?.toString(), // Use order ID as purchaseId\n lineItems: event.line_items.map((item: any) => ({\n id: item.id,\n title: item.title,\n quantity: item.quantity,\n variantId: item.variant_id,\n productId: item.product_id,\n })),\n createdAt: event.created_at,\n updatedAt: event.updated_at,\n };\n\n return { fulfillment, type: \"fulfillment_created\" };\n}\n\nexport async function cancelPurchaseWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: ShopifyPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const hmac = headers[\"x-shopify-hmac-sha256\"];\n if (!hmac) {\n throw new Error(\"Missing webhook HMAC\");\n }\n\n const order = {\n id: event.id,\n name: event.name,\n cancelReason: event.cancel_reason,\n cancelledAt: event.cancelled_at,\n refund: event.refunds?.[0] || null,\n };\n\n return { order, type: \"purchase_cancelled\" };\n}\n\n// Required OAuth scopes for Shopify channel integration\nconst REQUIRED_SCOPES = \"read_products,write_products,read_orders,write_orders,read_inventory,write_inventory\";\n\nexport function scopes() {\n return REQUIRED_SCOPES;\n}", "export async function executeChannelAdapterFunction({ platform, functionName, args }: { platform: any; functionName: string; args: any }) {\n const functionPath = platform[functionName];\n\n if (functionPath.startsWith(\"http\")) {\n const response = await fetch(functionPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform, ...args }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP request failed: ${response.statusText}`);\n }\n return response.json();\n }\n\n const adapter = await import(\n `../${functionPath}.ts`\n );\n\n const fn = adapter[functionName];\n if (!fn) {\n throw new Error(\n `Function ${functionName} not found in adapter ${functionPath}`\n );\n }\n\n try {\n return await fn({ platform, ...args });\n } catch (error) {\n throw new Error(\n `Error executing ${functionName} for platform ${functionPath}: ${(error as Error).message}`\n );\n }\n}\n\n// Helper functions for common channel operations\nexport async function searchChannelProducts({ platform, searchEntry, after }: { platform: any; searchEntry: string; after?: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"searchProductsFunction\",\n args: { searchEntry, after },\n });\n}\n\nexport async function getChannelProduct({ platform, productId }: { platform: any; productId: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"getProductFunction\",\n args: { productId },\n });\n}\n\nexport async function createChannelPurchase({ platform, cartItems, shipping, notes }: { platform: any; cartItems: any; shipping: any; notes?: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"createPurchaseFunction\",\n args: { cartItems, shipping, notes },\n });\n}\n\nexport async function createChannelWebhook({ platform, endpoint, events }: { platform: any; endpoint: string; events: string[] }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"createWebhookFunction\",\n args: { endpoint, events },\n });\n}\n\nexport async function deleteChannelWebhook({ platform, webhookId }: { platform: any; webhookId: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"deleteWebhookFunction\",\n args: { webhookId },\n });\n}\n\nexport async function getChannelWebhooks({ platform }: { platform: any }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"getWebhooksFunction\",\n args: {},\n });\n}\n\nexport async function handleChannelOAuth({ platform, callbackUrl }: { platform: any; callbackUrl: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"oAuthFunction\",\n args: { callbackUrl },\n });\n}\n\nexport async function handleChannelOAuthCallback({ platform, code, shop, state, appKey, appSecret, redirectUri }: { platform: any; code?: string; shop?: string; state?: string; appKey?: string; appSecret?: string; redirectUri?: string }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"oAuthCallbackFunction\",\n args: { code, shop, state, appKey, appSecret, redirectUri },\n });\n}\n\nexport async function handleChannelTrackingWebhook({ platform, event, headers }: { platform: any; event: any; headers: any }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"createTrackingWebhookHandler\",\n args: { event, headers },\n });\n}\n\nexport async function handleChannelCancelWebhook({ platform, event, headers }: { platform: any; event: any; headers: any }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: \"cancelPurchaseWebhookHandler\",\n args: { event, headers },\n });\n}", "import { GraphQLClient, gql } from \"graphql-request\";\nimport { getBaseUrl } from '@/features/dashboard/lib/getBaseUrl';\nimport { keystoneContext } from '@/features/keystone/context';\n\ninterface OpenFrontPlatform {\n domain: string;\n accessToken: string;\n refreshToken?: string;\n tokenExpiresAt?: Date | string;\n appKey?: string;\n appSecret?: string;\n}\n\ninterface SearchProductsArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface GetProductArgs {\n productId: string;\n variantId?: string;\n}\n\ninterface SearchOrdersArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface UpdateProductArgs {\n productId: string;\n variantId: string;\n inventory?: number;\n price?: string;\n}\n\ninterface CreateWebhookArgs {\n endpoint: string;\n events: string[];\n}\n\ninterface DeleteWebhookArgs {\n webhookId: string;\n}\n\ninterface OAuthArgs {\n callbackUrl: string;\n}\n\ninterface OAuthCallbackArgs {\n code: string;\n shop: string;\n state: string;\n}\n\ninterface WebhookEventArgs {\n event: any;\n headers: Record;\n}\n\n// Helper function to get fresh access token with proper OAuth 2.0 flow\nconst getFreshAccessToken = async (platform: OpenFrontPlatform) => {\n console.log('\uD83D\uDD04 [OpenFront Shop] getFreshAccessToken called');\n console.log('\uD83D\uDD04 [OpenFront Shop] Platform domain:', platform.domain);\n console.log('\uD83D\uDD04 [OpenFront Shop] Actual access token:', platform.accessToken);\n \n // Get shop with OAuth credentials from database\n const shops = await keystoneContext.sudo().query.Shop.findMany({\n where: { \n domain: { equals: platform.domain },\n accessToken: { equals: platform.accessToken }\n },\n query: 'id refreshToken tokenExpiresAt platform { appKey appSecret }'\n });\n \n if (!shops || shops.length === 0) {\n console.log('\u26A0\uFE0F [OpenFront Shop] No matching shop found in database');\n return platform.accessToken;\n }\n \n const shop = shops[0];\n console.log('\uD83D\uDD04 [OpenFront Shop] Found shop:', shop.id);\n console.log('\uD83D\uDD04 [OpenFront Shop] Has refresh token:', !!shop.refreshToken);\n console.log('\uD83D\uDD04 [OpenFront Shop] Token expires at:', shop.tokenExpiresAt);\n console.log('\uD83D\uDD04 [OpenFront Shop] Has appKey:', !!shop.platform?.appKey);\n console.log('\uD83D\uDD04 [OpenFront Shop] Has appSecret:', !!shop.platform?.appSecret);\n console.log('\uD83D\uDD04 [OpenFront Shop] Actual refresh token:', shop.refreshToken);\n \n // If we have a refresh token, check if we need to refresh\n if (shop.refreshToken) {\n console.log('\uD83D\uDD04 [OpenFront Shop] Refresh token found, checking if refresh needed');\n \n // Check if access token has expired (if we have expiry info)\n let shouldRefresh = false;\n \n if (shop.tokenExpiresAt) {\n const expiresAt = typeof shop.tokenExpiresAt === 'string' \n ? new Date(shop.tokenExpiresAt) \n : shop.tokenExpiresAt;\n \n const now = new Date();\n shouldRefresh = expiresAt <= now;\n \n console.log('\uD83D\uDD04 [OpenFront Shop] Token expiry check:');\n console.log('\uD83D\uDD04 [OpenFront Shop] - Expires at:', expiresAt.toISOString());\n console.log('\uD83D\uDD04 [OpenFront Shop] - Current time:', now.toISOString());\n console.log('\uD83D\uDD04 [OpenFront Shop] - Should refresh:', shouldRefresh);\n } else {\n // If no expiry info, assume token needs refresh\n shouldRefresh = true;\n console.log('\uD83D\uDD04 [OpenFront Shop] No expiry info found, assuming refresh needed');\n }\n \n if (shouldRefresh) {\n console.log('\uD83D\uDD04 [OpenFront Shop] Starting token refresh process...');\n \n // Use refresh token to get new access token\n const tokenUrl = `${platform.domain}/api/oauth/token`;\n console.log('\uD83D\uDD04 [OpenFront Shop] Token URL:', tokenUrl);\n \n const formData = new URLSearchParams({\n grant_type: \"refresh_token\",\n refresh_token: shop.refreshToken,\n client_id: shop.platform?.appKey || \"\",\n client_secret: shop.platform?.appSecret || \"\",\n });\n\n console.log('\uD83D\uDD04 [OpenFront Shop] Refresh request params:');\n console.log('\uD83D\uDD04 [OpenFront Shop] - grant_type: refresh_token');\n console.log('\uD83D\uDD04 [OpenFront Shop] - client_id:', shop.platform?.appKey || \"NOT_SET\");\n console.log('\uD83D\uDD04 [OpenFront Shop] - client_secret:', shop.platform?.appSecret ? \"SET\" : \"NOT_SET\");\n console.log('\uD83D\uDD04 [OpenFront Shop] - refresh_token:', shop.refreshToken ? \"SET\" : \"NOT_SET\");\n\n console.log('\uD83D\uDD04 [OpenFront Shop] Making refresh token request...');\n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: formData,\n });\n\n console.log('\uD83D\uDD04 [OpenFront Shop] Refresh response status:', response.status);\n console.log('\uD83D\uDD04 [OpenFront Shop] Refresh response ok:', response.ok);\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error('\uD83D\uDEA8 [OpenFront Shop] Token refresh failed:', errorText);\n console.error('\uD83D\uDEA8 [OpenFront Shop] Response status:', response.status);\n console.error('\uD83D\uDEA8 [OpenFront Shop] Response statusText:', response.statusText);\n throw new Error(`Failed to refresh access token: ${response.statusText} - ${errorText}`);\n }\n\n const tokenData = await response.json();\n console.log('\uD83D\uDD04 [OpenFront Shop] Token refresh response received');\n console.log('\uD83D\uDD04 [OpenFront Shop] - Has access_token:', !!tokenData.access_token);\n console.log('\uD83D\uDD04 [OpenFront Shop] - Has refresh_token:', !!tokenData.refresh_token);\n console.log('\uD83D\uDD04 [OpenFront Shop] - Expires in:', tokenData.expires_in, 'seconds');\n \n const { access_token, refresh_token, expires_in } = tokenData;\n \n // Update stored access token and expiry in database\n console.log('\uD83D\uDD04 [OpenFront Shop] Updating tokens in database...');\n try {\n console.log('\uD83D\uDD04 [OpenFront Shop] Updating shop:', shop.id);\n await keystoneContext.sudo().query.Shop.updateOne({\n where: { id: shop.id },\n data: {\n accessToken: access_token,\n ...(refresh_token && { refreshToken: refresh_token }),\n ...(expires_in && { tokenExpiresAt: new Date(Date.now() + (expires_in * 1000)) })\n }\n });\n console.log('\u2705 [OpenFront Shop] Shop updated with new tokens:', shop.id);\n } catch (error) {\n console.error('\uD83D\uDEA8 [OpenFront Shop] Failed to update shop tokens in database:', error);\n // Continue with the request even if database update fails\n }\n \n console.log('\u2705 [OpenFront Shop] Returning fresh access token');\n return access_token;\n } else {\n // Token hasn't expired yet, use existing one\n console.log('\u2705 [OpenFront Shop] Token still valid, using existing access token');\n return platform.accessToken;\n }\n }\n \n // If no refresh token, just use the access token as-is\n console.log('\u26A0\uFE0F [OpenFront Shop] No refresh token available, using existing access token');\n return platform.accessToken;\n};\n\n// Helper function to create OpenFront GraphQL client with fresh token\nconst createOpenFrontClient = async (platform: OpenFrontPlatform) => {\n const freshAccessToken = await getFreshAccessToken(platform);\n \n return new GraphQLClient(\n `${platform.domain}/api/graphql`,\n {\n headers: {\n \"Authorization\": `Bearer ${freshAccessToken}`,\n \"Content-Type\": \"application/json\",\n },\n }\n );\n};\n\n// Helper function to get product image URL\n// imagePath is a relative path (e.g., \"/images/product.jpg\") that needs domain prepended\n// image.url is an absolute S3 URL that can be used directly\nconst getProductImageUrl = (productImage: any, domain: string): string | null => {\n if (productImage?.imagePath) {\n return `${domain}${productImage.imagePath}`;\n }\n return productImage?.image?.url || null;\n};\n\n// Function to search products\nexport async function searchProductsFunction({ \n platform, \n searchEntry, \n after \n}: { \n platform: OpenFrontPlatform; \n searchEntry: string; \n after?: string; \n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const gqlQuery = gql`\n query SearchProducts($where: ProductWhereInput, $take: Int, $skip: Int) {\n products(where: $where, take: $take, skip: $skip, orderBy: { createdAt: desc }) {\n id\n title\n handle\n description {\n document\n }\n productImages {\n image {\n url\n }\n imagePath\n }\n productVariants {\n id\n title\n sku\n inventoryQuantity\n prices {\n id\n amount\n currency {\n code\n }\n region {\n countries {\n iso2\n }\n }\n }\n }\n productCollections {\n id\n title\n }\n metadata\n status\n createdAt\n }\n productsCount(where: $where)\n }\n `;\n\n // Build search filter\n const where: any = {\n status: { equals: \"published\" }\n };\n\n if (searchEntry && searchEntry.trim()) {\n where.OR = [\n { title: { contains: searchEntry, mode: \"insensitive\" } },\n { handle: { contains: searchEntry, mode: \"insensitive\" } },\n { productVariants: { some: { sku: { contains: searchEntry, mode: \"insensitive\" } } } }\n ];\n }\n\n // Handle pagination\n const take = 15;\n const skip = after ? parseInt(Buffer.from(after, 'base64').toString()) : 0;\n\n const { products, productsCount } = await openFrontClient.request(gqlQuery, {\n where,\n take,\n skip,\n }) as any;\n\n if (!products || products.length === 0) {\n throw new Error(\"No products found from OpenFront\");\n }\n\n // Transform products to Openship format\n const transformedProducts = products.flatMap((product: any) => \n product.productVariants.map((variant: any) => {\n const firstPrice = variant.prices[0];\n const firstImage = product.productImages[0];\n \n return {\n image: getProductImageUrl(firstImage, platform.domain),\n title: `${product.title} - ${variant.title}`,\n productId: product.id,\n variantId: variant.id,\n price: firstPrice ? (firstPrice.amount / 100).toFixed(2) : \"0.00\", // Convert from cents\n availableForSale: product.status === \"published\" && variant.inventoryQuantity > 0,\n inventory: variant.inventoryQuantity || 0,\n inventoryTracked: true,\n productLink: `https://${platform.domain}/products/${product.handle}`,\n cursor: Buffer.from((skip + products.indexOf(product) + 1).toString()).toString('base64'),\n };\n })\n );\n\n const hasNextPage = skip + take < productsCount;\n const endCursor = hasNextPage ? Buffer.from((skip + take).toString()).toString('base64') : null;\n\n return { \n products: transformedProducts, \n pageInfo: {\n hasNextPage,\n endCursor\n }\n };\n}\n\n// Function to get a specific product by variantId and productId\nexport async function getProductFunction({\n platform,\n productId,\n variantId,\n}: {\n platform: OpenFrontPlatform;\n productId: string;\n variantId?: string;\n}) {\n console.log(\"OpenFront getProductFunction called with:\", { platform: platform.domain, productId, variantId });\n \n const openFrontClient = await createOpenFrontClient(platform);\n\n // Build the query conditionally based on whether variantId is provided\n const gqlQuery = variantId ? gql`\n query GetProduct($productId: ID!, $variantId: ID!) {\n product(where: { id: $productId }) {\n id\n title\n handle\n description {\n document\n }\n productImages {\n image {\n url\n }\n imagePath\n }\n productVariants(where: { id: { equals: $variantId } }) {\n id\n title\n sku\n inventoryQuantity\n prices {\n id\n amount\n currency {\n code\n }\n }\n }\n status\n }\n }\n ` : gql`\n query GetProduct($productId: ID!) {\n product(where: { id: $productId }) {\n id\n title\n handle\n description {\n document\n }\n productImages {\n image {\n url\n }\n imagePath\n }\n productVariants {\n id\n title\n sku\n inventoryQuantity\n prices {\n id\n amount\n currency {\n code\n }\n }\n }\n status\n }\n }\n `;\n\n const variables: any = { productId };\n if (variantId) {\n variables.variantId = variantId;\n }\n\n const { product } = await openFrontClient.request(gqlQuery, variables) as any;\n\n if (!product) {\n throw new Error(\"Product not found from OpenFront\");\n }\n\n const variant = variantId \n ? product.productVariants.find((v: any) => v.id === variantId)\n : product.productVariants[0];\n\n if (!variant) {\n throw new Error(\"Product variant not found from OpenFront\");\n }\n\n const firstPrice = variant.prices[0];\n const firstImage = product.productImages[0];\n\n const transformedProduct = {\n image: getProductImageUrl(firstImage, platform.domain),\n title: `${product.title} - ${variant.title}`,\n productId: product.id,\n variantId: variant.id,\n price: firstPrice ? (firstPrice.amount / 100).toFixed(2) : \"0.00\",\n availableForSale: product.status === \"published\" && variant.inventoryQuantity > 0,\n inventory: variant.inventoryQuantity || 0,\n inventoryTracked: true,\n productLink: `https://${platform.domain}/products/${product.handle}`,\n };\n\n return { product: transformedProduct };\n}\n\nexport async function searchOrdersFunction({\n platform,\n searchEntry,\n after,\n}: {\n platform: OpenFrontPlatform;\n searchEntry: string;\n after?: string;\n}) {\n console.log(\"fuckkk\")\n const openFrontClient = await createOpenFrontClient(platform);\n\n const gqlQuery = gql`\n query SearchOrders($where: OrderWhereInput, $take: Int, $skip: Int) {\n orders(where: $where, take: $take, skip: $skip, orderBy: { createdAt: desc }) {\n id\n displayId\n email\n status\n total\n rawTotal\n currency {\n code\n }\n shippingAddress {\n firstName\n lastName\n address1\n address2\n city\n province\n postalCode\n phone\n country {\n iso2\n }\n }\n lineItems {\n id\n title\n quantity\n sku\n variantTitle\n thumbnail\n formattedUnitPrice\n formattedTotal\n moneyAmount {\n amount\n originalAmount\n }\n productVariant {\n id\n title\n sku\n product {\n id\n title\n handle\n thumbnail\n }\n }\n productData\n variantData\n }\n createdAt\n updatedAt\n }\n ordersCount(where: $where)\n }\n `;\n\n // Build search filter\n const where: any = {};\n\n if (searchEntry && searchEntry.trim()) {\n where.OR = [\n { displayId: { contains: searchEntry, mode: \"insensitive\" } },\n { email: { contains: searchEntry, mode: \"insensitive\" } },\n { shippingAddress: { \n is: {\n OR: [\n { firstName: { contains: searchEntry, mode: \"insensitive\" } },\n { lastName: { contains: searchEntry, mode: \"insensitive\" } }\n ]\n }\n }}\n ];\n }\n\n // Handle pagination\n const take = 15;\n const skip = after ? parseInt(Buffer.from(after, 'base64').toString()) : 0;\n\n const { orders, ordersCount } = await openFrontClient.request(gqlQuery, {\n where,\n take,\n skip,\n }) as any;\n\n console.log(\"Orders from OpenFront:\", orders);\n\n // Transform orders to Openship format\n const transformedOrders = orders.map((order: any) => {\n const shippingAddress = order.shippingAddress || {};\n \n return {\n orderId: order.id,\n orderName: `#${order.displayId}`,\n link: `${platform.domain}/admin/orders/${order.id}`,\n date: new Date(order.createdAt).toLocaleDateString(),\n firstName: shippingAddress.firstName || \"\",\n lastName: shippingAddress.lastName || \"\",\n streetAddress1: shippingAddress.address1 || \"\",\n streetAddress2: shippingAddress.address2 || \"\",\n city: shippingAddress.city || \"\",\n state: shippingAddress.province || \"\",\n zip: shippingAddress.postalCode || \"\",\n country: shippingAddress.country?.iso2 || \"\",\n email: order.email || \"\",\n fulfillmentStatus: order.status,\n financialStatus: order.status,\n totalPrice: order.rawTotal ? (order.rawTotal / 100).toFixed(2) : \"0.00\",\n currency: order.currency?.code || \"USD\",\n lineItems: (order.lineItems || []).map((lineItem: any) => {\n // Combine product title and variant title like in channel search\n const productTitle = lineItem.productVariant?.product?.title || '';\n const variantTitle = lineItem.productVariant?.title || '';\n const combinedTitle = productTitle && variantTitle ? `${productTitle} - ${variantTitle}` : lineItem.title;\n \n return {\n lineItemId: lineItem.id,\n name: combinedTitle,\n quantity: lineItem.quantity,\n image: getProductImageUrl({ imagePath: lineItem.thumbnail, image: { url: lineItem.productVariant?.product?.thumbnail } }, platform.domain) || \"\",\n price: lineItem.moneyAmount ? (lineItem.moneyAmount.amount / 100).toFixed(2) : \"0.00\",\n variantId: lineItem.productVariant?.id || \"\",\n productId: lineItem.productVariant?.product?.id || \"\",\n sku: lineItem.sku || lineItem.productVariant?.sku || \"\",\n };\n }),\n cartItems: [],\n fulfillments: [],\n note: \"\",\n cursor: Buffer.from((skip + orders.indexOf(order) + 1).toString()).toString('base64'),\n };\n });\n\n console.log(\"Transformed orders:\", transformedOrders);\n\n const hasNextPage = skip + take < ordersCount;\n const endCursor = hasNextPage ? Buffer.from((skip + take).toString()).toString('base64') : null;\n\n return { \n orders: transformedOrders, \n pageInfo: {\n hasNextPage,\n endCursor\n }\n };\n}\n\nexport async function updateProductFunction({\n platform,\n productId,\n variantId,\n inventory,\n price,\n}: {\n platform: OpenFrontPlatform;\n productId: string;\n variantId: string;\n inventory?: number;\n price?: string;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const mutations = [];\n\n if (inventory !== undefined) {\n const updateInventoryMutation = gql`\n mutation UpdateProductVariantInventory($where: ProductVariantWhereUniqueInput!, $data: ProductVariantUpdateInput!) {\n updateProductVariant(where: $where, data: $data) {\n id\n inventoryQuantity\n }\n }\n `;\n\n mutations.push(\n openFrontClient.request(updateInventoryMutation, {\n where: { id: variantId },\n data: { inventoryQuantity: inventory },\n })\n );\n }\n\n if (price !== undefined) {\n // Note: Price updates in OpenFront might require updating the Price model separately\n // This is a simplified approach - you might need to adjust based on your schema\n console.log(`Price update requested for variant ${variantId}: ${price}`);\n // Actual price update would depend on how prices are structured in OpenFront\n }\n\n const results = await Promise.all(mutations);\n return { success: true, results };\n}\n\nexport async function createWebhookFunction({\n platform,\n endpoint,\n events,\n}: {\n platform: OpenFrontPlatform;\n endpoint: string;\n events: string[];\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const createWebhookMutation = gql`\n mutation CreateWebhookEndpoint($data: WebhookEndpointCreateInput!) {\n createWebhookEndpoint(data: $data) {\n id\n url\n events\n isActive\n secret\n }\n }\n `;\n\n // Map Openship events to OpenFront events\n const eventMap: Record = {\n ORDER_CREATED: \"order.created\",\n ORDER_CANCELLED: \"order.cancelled\",\n TRACKING_CREATED: \"fulfillment.created\",\n };\n\n const openFrontEvents = events.map(event => eventMap[event] || event);\n\n const result = await openFrontClient.request(createWebhookMutation, {\n data: {\n url: endpoint,\n events: openFrontEvents,\n isActive: true,\n },\n }) as any;\n\n const webhook = result.createWebhookEndpoint;\n\n return { \n webhooks: [webhook], \n webhookId: webhook.id \n };\n}\n\nexport async function deleteWebhookFunction({\n platform,\n webhookId,\n}: {\n platform: OpenFrontPlatform;\n webhookId: string;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const deleteWebhookMutation = gql`\n mutation DeleteWebhookEndpoint($where: WebhookEndpointWhereUniqueInput!) {\n deleteWebhookEndpoint(where: $where) {\n id\n }\n }\n `;\n\n const result = await openFrontClient.request(deleteWebhookMutation, {\n where: { id: webhookId },\n });\n\n return result;\n}\n\nexport async function getWebhooksFunction({\n platform,\n}: {\n platform: OpenFrontPlatform;\n}) {\n const openFrontClient = await createOpenFrontClient(platform);\n\n const query = gql`\n query GetWebhookEndpoints {\n webhookEndpoints(where: { isActive: { equals: true } }) {\n id\n url\n events\n isActive\n createdAt\n }\n }\n `;\n\n const { webhookEndpoints } = await openFrontClient.request(query) as any;\n\n const baseUrl = await getBaseUrl();\n \n // Map OpenFront events back to Openship events\n const eventMap: Record = {\n \"order.created\": \"ORDER_CREATED\",\n \"order.cancelled\": \"ORDER_CANCELLED\", \n \"fulfillment.created\": \"TRACKING_CREATED\",\n };\n\n const webhooks = webhookEndpoints.map((webhook: any) => ({\n id: webhook.id,\n callbackUrl: webhook.url.replace(baseUrl, \"\"),\n topic: webhook.events.map((event: string) => eventMap[event] || event),\n format: \"JSON\",\n createdAt: webhook.createdAt,\n }));\n\n return { webhooks };\n}\n\nexport async function oAuthFunction({\n platform,\n callbackUrl,\n}: {\n platform: OpenFrontPlatform;\n callbackUrl: string;\n}) {\n \n if (!platform.appKey) {\n throw new Error(\"OpenFront OAuth requires appKey in platform configuration\");\n }\n \n // Generate OpenFront OAuth URL\n const scopes = \"read_products,write_products,read_orders,write_orders,read_customers,write_customers,read_webhooks,write_webhooks\";\n const state = (platform as any).state || Math.random().toString(36).substring(7);\n \n // Redirect to apps page with install popup\n const openFrontAuthUrl = `${platform.domain}/dashboard/platform/apps?` +\n `install=true&` +\n `client_id=${platform.appKey}&` +\n `scope=${encodeURIComponent(scopes)}&` +\n `redirect_uri=${encodeURIComponent(callbackUrl)}&` +\n `state=${state}&` +\n `response_type=code`;\n \n \n return { authUrl: openFrontAuthUrl };\n}\n\nexport async function oAuthCallbackFunction({\n platform,\n code,\n shop,\n state,\n appKey,\n appSecret,\n redirectUri,\n}: {\n platform: OpenFrontPlatform;\n code: string;\n shop: string;\n state: string;\n appKey?: string;\n appSecret?: string;\n redirectUri?: string;\n}) {\n // Use platform domain or shop parameter\n const domain = platform.domain || shop;\n const tokenUrl = `${domain}/api/oauth/token`;\n \n // Use passed credentials first (for flexibility), then platform's credentials\n const clientId = appKey || platform.appKey;\n const clientSecret = appSecret || platform.appSecret;\n \n \n if (!clientId || !clientSecret) {\n throw new Error(\"OpenFront OAuth requires appKey and appSecret in platform configuration or as parameters\");\n }\n \n const formData = new URLSearchParams({\n grant_type: \"authorization_code\",\n client_id: clientId,\n client_secret: clientSecret,\n code,\n redirect_uri: redirectUri || \"\",\n });\n\n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body: formData,\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n console.error(\"OpenFront OAuth error:\", errorText);\n throw new Error(`Failed to exchange OAuth code for access token: ${response.statusText}`);\n }\n\n const { access_token, refresh_token, expires_in } = await response.json();\n \n // Return OAuth response with refresh token support\n return {\n accessToken: access_token,\n refreshToken: refresh_token,\n expiresIn: expires_in,\n tokenExpiresAt: new Date(Date.now() + (expires_in * 1000)).toISOString()\n };\n}\n\nexport async function createOrderWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: OpenFrontPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity using OpenFront's signature\n const signature = headers[\"x-openfront-webhook-signature\"] || headers[\"X-OpenFront-Webhook-Signature\"];\n if (!signature) {\n console.error(\"Missing webhook signature. Available headers:\", Object.keys(headers));\n throw new Error(\"Missing webhook signature\");\n }\n\n // Transform OpenFront order to Openship format\n const lineItemsOutput = event.data?.lineItems?.map((item: any) => {\n // Combine product title and variant title like in channel search\n const productTitle = item.productVariant?.product?.title || '';\n const variantTitle = item.productVariant?.title || '';\n const combinedTitle = productTitle && variantTitle ? `${productTitle} - ${variantTitle}` : item.title;\n \n return {\n name: combinedTitle,\n image: getProductImageUrl(item.productVariant?.product?.productImages?.[0], platform.domain) || item.thumbnail,\n price: item.moneyAmount?.amount ? (item.moneyAmount.amount / 100) : 0, // Convert from cents to float\n quantity: item.quantity || 0,\n productId: item.productVariant?.product?.id?.toString(),\n variantId: item.productVariant?.id?.toString(),\n sku: item.productVariant?.sku || item.sku || \"\",\n lineItemId: item.id?.toString(),\n };\n }) || [];\n\n // Return Keystone-ready order data\n const orderData = event.data;\n const shippingAddress = orderData.shippingAddress || {};\n \n return {\n orderId: orderData.id?.toString(),\n orderName: orderData.displayId ? `#${orderData.displayId}` : \"\",\n email: orderData.email || \"\",\n firstName: shippingAddress.firstName || \"\",\n lastName: shippingAddress.lastName || \"\",\n streetAddress1: shippingAddress.address1 || \"\",\n streetAddress2: shippingAddress.address2 || \"\",\n city: shippingAddress.city || \"\",\n state: shippingAddress.province || \"\",\n zip: shippingAddress.postalCode || \"\",\n country: shippingAddress.country?.iso2?.toUpperCase() || \"\",\n phone: shippingAddress.phone || \"\",\n currency: orderData.currency?.code?.toUpperCase() || \"USD\",\n totalPrice: orderData.rawTotal ? (orderData.rawTotal / 100) : 0, // rawTotal is in cents, convert to float\n subTotalPrice: parseFloat(orderData.subtotal?.replace(/[$,]/g, '') || '0'), // Parse formatted string to float\n totalDiscounts: parseFloat(orderData.discount?.replace(/[$,]/g, '') || '0'), // Parse formatted string to float\n totalTax: parseFloat(orderData.tax?.replace(/[$,]/g, '') || '0'), // Parse formatted string to float\n status: \"INPROCESS\",\n linkOrder: true,\n matchOrder: true,\n processOrder: true,\n lineItems: { create: lineItemsOutput },\n };\n}\n\nexport async function cancelOrderWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: OpenFrontPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const signature = headers[\"x-openfront-webhook-signature\"];\n if (!signature) {\n throw new Error(\"Missing webhook signature\");\n }\n\n const orderData = event.data;\n const order = {\n id: orderData.id,\n name: orderData.orderNumber,\n cancelReason: orderData.cancellationReason || \"merchant_cancelled\",\n cancelledAt: new Date().toISOString(),\n };\n\n return { order, type: \"order_cancelled\" };\n}\n\n// Required OAuth scopes for OpenFront shop integration\nconst REQUIRED_SCOPES = \"read_products,write_products,read_orders,write_orders,read_customers,write_customers,read_webhooks,write_webhooks\";\n\nexport function scopes() {\n return REQUIRED_SCOPES;\n}\n\nexport async function addTrackingFunction({\n order,\n trackingCompany,\n trackingNumber,\n}: {\n order: any;\n trackingCompany: string;\n trackingNumber: string;\n}) {\n const openFrontClient = await createOpenFrontClient({\n domain: order.shop.domain,\n accessToken: order.shop.accessToken,\n });\n\n // Create fulfillment record in OpenFront\n const createFulfillmentMutation = gql`\n mutation CreateFulfillment($data: FulfillmentCreateInput!) {\n createFulfillment(data: $data) {\n id\n trackingNumber\n trackingCompany\n }\n }\n `;\n\n const fulfillmentData = {\n order: { connect: { id: order.orderId } },\n trackingNumber,\n trackingCompany,\n status: \"shipped\",\n };\n\n const result = await openFrontClient.request(createFulfillmentMutation, {\n data: fulfillmentData,\n });\n\n return result;\n}", "import { GraphQLClient, gql } from \"graphql-request\";\nimport { getBaseUrl } from '@/features/dashboard/lib/getBaseUrl';\n\ninterface ShopifyPlatform {\n domain: string;\n accessToken: string;\n appKey?: string;\n appSecret?: string;\n}\n\ninterface SearchProductsArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface GetProductArgs {\n productId: string;\n variantId?: string;\n}\n\ninterface SearchOrdersArgs {\n searchEntry: string;\n after?: string;\n}\n\ninterface UpdateProductArgs {\n productId: string;\n variantId: string;\n inventory?: number;\n price?: string;\n}\n\ninterface CreateWebhookArgs {\n endpoint: string;\n events: string[];\n}\n\ninterface DeleteWebhookArgs {\n webhookId: string;\n}\n\ninterface OAuthArgs {\n callbackUrl: string;\n}\n\ninterface OAuthCallbackArgs {\n code: string;\n shop: string;\n state: string;\n}\n\ninterface WebhookEventArgs {\n event: any;\n headers: Record;\n}\n\n// Function to search products\nexport async function searchProductsFunction({ \n platform, \n searchEntry, \n after \n}: { \n platform: ShopifyPlatform; \n searchEntry: string; \n after?: string; \n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const gqlQuery = gql`\n query SearchProducts($query: String, $after: String) {\n productVariants(first: 15, query: $query, after: $after) {\n edges {\n node {\n id\n availableForSale\n image {\n originalSrc\n }\n price\n title\n product {\n id\n handle\n title\n images(first: 1) {\n edges {\n node {\n originalSrc\n }\n }\n }\n }\n inventoryQuantity\n inventoryPolicy\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n `;\n\n const { productVariants } = await shopifyClient.request(gqlQuery, {\n query: searchEntry,\n after,\n }) as any;\n\n if (productVariants.edges.length < 1) {\n throw new Error(\"No products found from Shopify\");\n }\n\n const products = productVariants.edges.map(({ node, cursor }: any) => ({\n image:\n node.image?.originalSrc || node.product.images.edges[0]?.node.originalSrc,\n title: `${node.product.title} - ${node.title}`,\n productId: node.product.id.split(\"/\").pop(),\n variantId: node.id.split(\"/\").pop(),\n price: node.price,\n availableForSale: node.availableForSale,\n inventory: node.inventoryQuantity,\n inventoryTracked: node.inventoryPolicy !== \"deny\",\n productLink: `https://${platform.domain}/products/${node.product.handle}`,\n cursor,\n }));\n\n return { \n products, \n pageInfo: productVariants.pageInfo \n };\n}\n\n// Function to get a specific product by variantId and productId\nexport async function getProductFunction({\n platform,\n productId,\n variantId,\n}: {\n platform: ShopifyPlatform;\n productId: string;\n variantId?: string;\n}) {\n console.log(\"SHOP getProductFunction called with:\", { platform: platform.domain, productId, variantId });\n \n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const gqlQuery = gql`\n query GetProduct($variantId: ID!) {\n productVariant(id: $variantId) {\n id\n availableForSale\n image {\n originalSrc\n }\n price\n title\n product {\n id\n handle\n title\n images(first: 1) {\n edges {\n node {\n originalSrc\n }\n }\n }\n }\n inventoryQuantity\n inventoryPolicy\n }\n }\n `;\n\n const fullVariantId = `gid://shopify/ProductVariant/${variantId}`;\n console.log(\"SHOP querying with variantId:\", fullVariantId);\n \n const { productVariant } = await shopifyClient.request(gqlQuery, {\n variantId: fullVariantId,\n }) as any;\n\n console.log(\"SHOP productVariant result:\", productVariant);\n\n if (!productVariant) {\n throw new Error(\"Product not found from Shopify\");\n }\n\n const product = {\n image:\n productVariant.image?.originalSrc ||\n productVariant.product.images.edges[0]?.node.originalSrc,\n title: `${productVariant.product.title} - ${productVariant.title}`,\n productId: productVariant.product.id.split(\"/\").pop(),\n variantId: productVariant.id.split(\"/\").pop(),\n price: productVariant.price,\n availableForSale: productVariant.availableForSale,\n inventory: productVariant.inventoryQuantity,\n inventoryTracked: productVariant.inventoryPolicy !== \"deny\",\n productLink: `https://${platform.domain}/admin/products/${productVariant.product.id\n .split(\"/\")\n .pop()}/variants/${productVariant.id.split(\"/\").pop()}`,\n };\n\n return { product };\n}\n\nexport async function searchOrdersFunction({\n platform,\n searchEntry,\n after,\n}: {\n platform: ShopifyPlatform;\n searchEntry: string;\n after?: string;\n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const gqlQuery = gql`\n query SearchOrders($query: String, $after: String) {\n orders(first: 15, query: $query, after: $after) {\n edges {\n node {\n id\n name\n email\n createdAt\n updatedAt\n displayFulfillmentStatus\n displayFinancialStatus\n totalPriceSet {\n presentmentMoney {\n amount\n currencyCode\n }\n }\n shippingAddress {\n firstName\n lastName\n address1\n address2\n city\n province\n provinceCode\n zip\n country\n countryCodeV2\n }\n lineItems(first: 10) {\n edges {\n node {\n id\n title\n quantity\n image {\n originalSrc\n }\n variant {\n id\n title\n price\n sku\n product {\n id\n title\n handle\n }\n }\n }\n }\n }\n }\n cursor\n }\n pageInfo {\n hasNextPage\n endCursor\n }\n }\n }\n `;\n\n const { orders } = await shopifyClient.request(gqlQuery, {\n query: searchEntry,\n after,\n }) as any;\n\n const formattedOrders = orders.edges.map(({ node, cursor }: any) => ({\n orderId: node.id.split(\"/\").pop(),\n orderName: node.name,\n link: `https://${platform.domain}/admin/orders/${node.id.split(\"/\").pop()}`,\n date: new Date(node.createdAt).toLocaleDateString(),\n firstName: node.shippingAddress?.firstName || \"\",\n lastName: node.shippingAddress?.lastName || \"\",\n streetAddress1: node.shippingAddress?.address1 || \"\",\n streetAddress2: node.shippingAddress?.address2 || \"\",\n city: node.shippingAddress?.city || \"\",\n state: node.shippingAddress?.provinceCode || \"\",\n zip: node.shippingAddress?.zip || \"\",\n country: node.shippingAddress?.countryCodeV2 || \"\",\n email: node.email || \"\",\n fulfillmentStatus: node.displayFulfillmentStatus,\n financialStatus: node.displayFinancialStatus,\n totalPrice: node.totalPriceSet.presentmentMoney.amount,\n currency: node.totalPriceSet.presentmentMoney.currencyCode,\n lineItems: node.lineItems.edges.map(({ node: lineItem }: any) => ({\n lineItemId: lineItem.id.split(\"/\").pop(),\n name: lineItem.title,\n quantity: lineItem.quantity,\n image: lineItem.image?.originalSrc || \"\",\n price: lineItem.variant?.price || \"0\",\n variantId: lineItem.variant?.id.split(\"/\").pop(),\n productId: lineItem.variant?.product.id.split(\"/\").pop(),\n sku: lineItem.variant?.sku || \"\",\n })),\n cartItems: [], // Would be populated if this order has cart items\n fulfillments: [], // Would need to be fetched if needed\n note: \"\",\n cursor,\n }));\n\n return { \n orders: formattedOrders, \n pageInfo: orders.pageInfo \n };\n}\n\nexport async function updateProductFunction({\n platform,\n productId,\n variantId,\n inventory,\n price,\n}: {\n platform: ShopifyPlatform;\n productId: string;\n variantId: string;\n inventory?: number;\n price?: string;\n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const mutations = [];\n\n if (price !== undefined) {\n const updatePriceMutation = gql`\n mutation UpdateProductVariantPrice($input: ProductVariantInput!) {\n productVariantUpdate(input: $input) {\n productVariant {\n id\n price\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n mutations.push(\n shopifyClient.request(updatePriceMutation, {\n input: {\n id: `gid://shopify/ProductVariant/${variantId}`,\n price: price,\n },\n })\n );\n }\n\n if (inventory !== undefined) {\n try {\n // Get current inventory and calculate absolute quantity\n const getVariantWithInventoryQuery = gql`\n query GetVariantWithInventory($id: ID!) {\n productVariant(id: $id) {\n inventoryQuantity\n inventoryItem {\n id\n }\n }\n }\n `;\n\n console.log('QUERYING FOR VARIANT ID:', variantId);\n console.log('FULL GID:', `gid://shopify/ProductVariant/${variantId}`);\n \n const variantData = await shopifyClient.request(getVariantWithInventoryQuery, {\n id: `gid://shopify/ProductVariant/${variantId}`,\n });\n\n console.log('VARIANT DATA RECEIVED:', JSON.stringify(variantData, null, 2));\n\n if (!(variantData as any).productVariant?.inventoryItem?.id) {\n console.log('FAILING BECAUSE NO inventoryItem.id');\n console.log('variantData structure:', variantData);\n console.log('productVariant:', (variantData as any).productVariant);\n console.log('inventoryItem:', (variantData as any).productVariant?.inventoryItem);\n throw new Error(\"Unable to find inventory item for variant\");\n }\n\n // Get the first location\n const getLocationsQuery = gql`\n query GetLocations {\n locations(first: 1) {\n edges {\n node {\n id\n name\n }\n }\n }\n }\n `;\n\n const locationsData = await shopifyClient.request(getLocationsQuery);\n const location = (locationsData as any).locations.edges[0]?.node;\n\n if (!location) {\n throw new Error(\"No locations found for shop\");\n }\n\n // Use inventory delta to adjust available inventory (not on-hand)\n const inventoryDelta = inventory;\n\n const updateInventoryMutation = gql`\n mutation InventoryAdjustQuantities($input: InventoryAdjustQuantitiesInput!) {\n inventoryAdjustQuantities(input: $input) {\n inventoryAdjustmentGroup {\n id\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n mutations.push(\n shopifyClient.request(updateInventoryMutation, {\n input: {\n reason: \"correction\",\n name: \"available\",\n changes: [\n {\n inventoryItemId: (variantData as any).productVariant.inventoryItem.id,\n locationId: location.id, \n delta: inventoryDelta\n }\n ]\n }\n })\n );\n } catch (inventoryError) {\n console.error(\"Error updating inventory:\", inventoryError);\n throw inventoryError;\n }\n }\n\n const results = await Promise.all(mutations);\n return { success: true, results };\n}\n\nexport async function createWebhookFunction({\n platform,\n endpoint,\n events,\n}: {\n platform: ShopifyPlatform;\n endpoint: string;\n events: string[];\n}) {\n\n const mapTopic = {\n ORDER_CREATED: \"ORDERS_CREATE\",\n ORDER_CANCELLED: \"ORDERS_CANCELLED\", \n ORDER_CHARGEBACKED: \"DISPUTES_CREATE\",\n TRACKING_CREATED: \"FULFILLMENTS_CREATE\",\n };\n\n if (!platform.domain) {\n throw new Error(\"Missing domain in platform configuration\");\n }\n\n if (!platform.accessToken) {\n throw new Error(\"Missing accessToken in platform configuration\");\n }\n\n\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const webhooks = [];\n\n for (const event of events) {\n const shopifyTopic = (mapTopic as Record)[event] || event;\n \n const mutation = gql`\n mutation webhookSubscriptionCreate($topic: WebhookSubscriptionTopic!, $webhookSubscription: WebhookSubscriptionInput!) {\n webhookSubscriptionCreate(topic: $topic, webhookSubscription: $webhookSubscription) {\n webhookSubscription {\n id\n endpoint {\n __typename\n ... on WebhookHttpEndpoint {\n callbackUrl\n }\n }\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n try {\n const result = await shopifyClient.request(mutation, {\n topic: shopifyTopic,\n webhookSubscription: {\n callbackUrl: endpoint,\n format: \"JSON\",\n },\n }) as any;\n\n\n if (result.webhookSubscriptionCreate.userErrors.length > 0) {\n throw new Error(\n `Error creating webhook: ${result.webhookSubscriptionCreate.userErrors[0].message}`\n );\n }\n\n webhooks.push(result.webhookSubscriptionCreate.webhookSubscription);\n } catch (error) {\n throw error;\n }\n }\n\n // Return the first webhook's ID for compatibility with existing code\n const webhookId = webhooks[0]?.id?.split(\"/\").pop();\n return { webhooks, webhookId };\n}\n\nexport async function deleteWebhookFunction({\n platform,\n webhookId,\n}: {\n platform: ShopifyPlatform;\n webhookId: string;\n}) {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const mutation = gql`\n mutation DeleteWebhook($id: ID!) {\n webhookSubscriptionDelete(id: $id) {\n deletedWebhookSubscriptionId\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const result = await shopifyClient.request(mutation, {\n id: `gid://shopify/WebhookSubscription/${webhookId}`,\n });\n\n return (result as any).webhookSubscriptionDelete;\n}\n\nexport async function getWebhooksFunction({\n platform,\n}: {\n platform: ShopifyPlatform;\n}) {\n const mapTopic = {\n ORDERS_CREATE: \"ORDER_CREATED\",\n ORDERS_CANCELLED: \"ORDER_CANCELLED\",\n DISPUTES_CREATE: \"ORDER_CHARGEBACKED\",\n FULFILLMENTS_CREATE: \"TRACKING_CREATED\",\n };\n\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"X-Shopify-Access-Token\": platform.accessToken,\n },\n }\n );\n\n const query = gql`\n query GetWebhooks {\n webhookSubscriptions(first: 50) {\n edges {\n node {\n id\n topic\n format\n createdAt\n endpoint {\n __typename\n ... on WebhookHttpEndpoint {\n callbackUrl\n }\n }\n }\n }\n }\n }\n `;\n\n const { webhookSubscriptions } = await shopifyClient.request(query) as any;\n\n const baseUrl = await getBaseUrl();\n const webhooks = webhookSubscriptions.edges.map(({ node }: any) => ({\n id: node.id.split(\"/\").pop(),\n callbackUrl: node.endpoint.callbackUrl.replace(baseUrl, \"\"),\n topic: (mapTopic as any)[node.topic] || node.topic,\n format: node.format,\n createdAt: node.createdAt,\n }));\n\n return { webhooks };\n}\n\nexport async function oAuthFunction({\n platform,\n callbackUrl,\n}: {\n platform: ShopifyPlatform;\n callbackUrl: string;\n}) {\n // Use platform's appKey if available, otherwise fall back to env variable for backward compatibility\n const clientId = platform.appKey || process.env.SHOPIFY_APP_KEY;\n \n if (!clientId) {\n throw new Error(\"Shopify OAuth requires appKey in platform config or SHOPIFY_APP_KEY environment variable\");\n }\n \n const scopes = \"read_products,write_products,read_orders,write_orders,read_inventory,write_inventory\";\n const shopifyAuthUrl = `https://${platform.domain}/admin/oauth/authorize?client_id=${clientId}&scope=${scopes}&redirect_uri=${callbackUrl}&state=${Math.random().toString(36).substring(7)}`;\n \n return { authUrl: shopifyAuthUrl };\n}\n\nexport async function oAuthCallbackFunction({\n platform,\n code,\n shop,\n state,\n}: {\n platform: ShopifyPlatform;\n code: string;\n shop: string;\n state: string;\n}) {\n // Use platform credentials if available, otherwise fall back to env variables for backward compatibility\n const clientId = platform.appKey || process.env.SHOPIFY_APP_KEY;\n const clientSecret = platform.appSecret || process.env.SHOPIFY_APP_SECRET;\n \n if (!clientId || !clientSecret) {\n throw new Error(\"Shopify OAuth requires appKey and appSecret in platform config or environment variables\");\n }\n \n const tokenUrl = `https://${shop}/admin/oauth/access_token`;\n \n const response = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n client_id: clientId,\n client_secret: clientSecret,\n code,\n }),\n });\n\n if (!response.ok) {\n throw new Error(\"Failed to exchange OAuth code for access token\");\n }\n\n const { access_token } = await response.json();\n \n return { \n accessToken: access_token,\n domain: shop,\n };\n}\n\nexport async function createOrderWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: ShopifyPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const hmac = headers[\"x-shopify-hmac-sha256\"];\n if (!hmac) {\n throw new Error(\"Missing webhook HMAC\");\n }\n\n // Process the order data and format for Keystone Order creation\n const lineItemsOutput = await Promise.all(\n event.line_items.map(async (item: any) => {\n // Get product variant image from Shopify\n let image = null;\n try {\n const shopifyClient = new GraphQLClient(\n `https://${platform.domain}/admin/api/graphql.json`,\n {\n headers: {\n 'X-Shopify-Access-Token': platform.accessToken,\n },\n }\n );\n\n const variantQuery = gql`\n query productVariant($id: ID!) {\n productVariant(id: $id) {\n image {\n originalSrc\n }\n product {\n images(first: 1) {\n edges {\n node {\n originalSrc\n }\n }\n }\n }\n }\n }\n `;\n\n const result = await shopifyClient.request(variantQuery, {\n id: `gid://shopify/ProductVariant/${item.variant_id}`,\n });\n\n image = (result as any).productVariant?.image?.originalSrc || \n (result as any).productVariant?.product?.images?.edges?.[0]?.node?.originalSrc || \n null;\n } catch (error) {\n console.warn(`Failed to fetch image for variant ${item.variant_id}:`, error instanceof Error ? error.message : 'Unknown error');\n }\n\n return {\n name: item.title,\n image,\n price: parseFloat(item.price),\n quantity: item.quantity,\n productId: item.product_id?.toString(),\n variantId: item.variant_id?.toString(),\n sku: item.sku || \"\",\n lineItemId: item.id?.toString(),\n };\n })\n );\n\n // Return Keystone-ready order data (same format as Dasher)\n return {\n orderId: event.id?.toString(),\n orderName: event.name,\n email: event.email,\n firstName: event.shipping_address?.first_name,\n lastName: event.shipping_address?.last_name,\n streetAddress1: event.shipping_address?.address1,\n streetAddress2: event.shipping_address?.address2,\n city: event.shipping_address?.city,\n state: event.shipping_address?.province_code,\n zip: event.shipping_address?.zip,\n country: event.shipping_address?.country_code,\n phone: event.shipping_address?.phone,\n currency: event.currency,\n totalPrice: parseFloat(event.total_price),\n subTotalPrice: parseFloat(event.subtotal_price || event.total_price),\n totalDiscounts: parseFloat(event.total_discounts || \"0\"),\n totalTax: parseFloat(event.total_tax || \"0\"),\n status: \"INPROCESS\",\n linkOrder: true,\n matchOrder: true,\n processOrder: true,\n lineItems: { create: lineItemsOutput },\n };\n}\n\nexport async function addTrackingFunction({\n order,\n trackingCompany,\n trackingNumber,\n}: {\n order: any;\n trackingCompany: string;\n trackingNumber: string;\n}) {\n const FETCH_FULFILLMENT_ORDER = gql`\n query ($id: ID!) {\n order(id: $id) {\n fulfillmentOrders(first: 1) {\n edges {\n node {\n id\n status\n fulfillments(first: 1) {\n edges {\n node {\n id\n trackingInfo {\n number\n }\n }\n }\n }\n }\n }\n }\n }\n }\n `;\n\n const UPDATE_FULFILLMENT_TRACKING_INFO = gql`\n mutation fulfillmentTrackingInfoUpdateV2(\n $fulfillmentId: ID!\n $trackingInfoInput: FulfillmentTrackingInput!\n ) {\n fulfillmentTrackingInfoUpdateV2(\n fulfillmentId: $fulfillmentId\n trackingInfoInput: $trackingInfoInput\n ) {\n fulfillment {\n id\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n\n const CREATE_FULFILLMENT = gql`\n mutation fulfillmentCreateV2($fulfillment: FulfillmentV2Input!) {\n fulfillmentCreateV2(fulfillment: $fulfillment) {\n fulfillment {\n id\n }\n userErrors {\n field\n message\n }\n }\n }\n `;\n \n const client = new GraphQLClient(\n `https://${order.shop.domain}/admin/api/graphql.json`,\n {\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-Shopify-Access-Token\": order.shop.accessToken,\n },\n }\n );\n\n const data = await client.request(FETCH_FULFILLMENT_ORDER, {\n id: `gid://shopify/Order/${order.orderId}`,\n }) as any;\n\n const fulfillmentOrder = data.order?.fulfillmentOrders?.edges?.[0]?.node;\n \n if (!fulfillmentOrder) {\n throw new Error(\"No fulfillment order found\");\n }\n\n if (fulfillmentOrder.status === \"CLOSED\") {\n const fulfillment = fulfillmentOrder.fulfillments.edges[0]?.node;\n if (fulfillment) {\n const updateResponseBody = await client.request(\n UPDATE_FULFILLMENT_TRACKING_INFO,\n {\n fulfillmentId: fulfillment.id,\n trackingInfoInput: {\n numbers: [\n trackingNumber,\n ...fulfillment.trackingInfo.map(({ number }: any) => number),\n ],\n },\n }\n );\n return updateResponseBody;\n }\n }\n\n const createResponseBody = await client.request(CREATE_FULFILLMENT, {\n fulfillment: {\n lineItemsByFulfillmentOrder: [\n {\n fulfillmentOrderId: fulfillmentOrder.id,\n },\n ],\n trackingInfo: {\n company: trackingCompany,\n numbers: [trackingNumber],\n },\n },\n });\n\n return createResponseBody;\n}\n\nexport async function cancelOrderWebhookHandler({\n platform,\n event,\n headers,\n}: {\n platform: ShopifyPlatform;\n event: any;\n headers: Record;\n}) {\n // Verify webhook authenticity\n const hmac = headers[\"x-shopify-hmac-sha256\"];\n if (!hmac) {\n throw new Error(\"Missing webhook HMAC\");\n }\n\n const order = {\n id: event.id,\n name: event.name,\n cancelReason: event.cancel_reason,\n cancelledAt: event.cancelled_at,\n };\n\n return { order, type: \"order_cancelled\" };\n}\n\n// Required OAuth scopes for Shopify shop integration\nconst REQUIRED_SCOPES = \"read_products,write_products,read_orders,write_orders,read_inventory,write_inventory\";\n\nexport function scopes() {\n return REQUIRED_SCOPES;\n}", "export async function executeShopAdapterFunction({ platform, functionName, args }: { platform: any; functionName: string; args: any }) {\n const functionPath = platform[functionName];\n\n if (functionPath.startsWith(\"http\")) {\n const response = await fetch(functionPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform, ...args }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP request failed: ${response.statusText}`);\n }\n return response.json();\n }\n\n const adapter = await import(\n `../${functionPath}.ts`\n );\n\n const fn = adapter[functionName];\n if (!fn) {\n throw new Error(\n `Function ${functionName} not found in adapter ${functionPath}`\n );\n }\n\n try {\n return await fn({ platform, ...args });\n } catch (error) {\n throw new Error(\n `Error executing ${functionName} for platform ${functionPath}: ${(error as Error).message}`\n );\n }\n}\n\n// Helper functions for common shop operations\nexport async function searchShopProducts({ platform, searchEntry, after }: { platform: any; searchEntry: string; after?: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"searchProductsFunction\",\n args: { searchEntry, after },\n });\n}\n\nexport async function getShopProduct({ platform, productId }: { platform: any; productId: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"getProductFunction\",\n args: { productId },\n });\n}\n\nexport async function searchShopOrders({ platform, searchEntry, after }: { platform: any; searchEntry: string; after?: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"searchOrdersFunction\",\n args: { searchEntry, after },\n });\n}\n\nexport async function updateShopProduct({ platform, productId, inventory, price }: { platform: any; productId: string; inventory?: number; price?: number }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"updateProductFunction\",\n args: { productId, inventory, price },\n });\n}\n\nexport async function addCartToPlatformOrder({ platform, cartItems, orderId }: { platform: any; cartItems: any; orderId: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"addCartToPlatformOrderFunction\",\n args: { cartItems, orderId },\n });\n}\n\nexport async function createShopWebhook({ platform, endpoint, events }: { platform: any; endpoint: string; events: string[] }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"createWebhookFunction\",\n args: { endpoint, events },\n });\n}\n\nexport async function deleteShopWebhook({ platform, webhookId }: { platform: any; webhookId: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"deleteWebhookFunction\",\n args: { webhookId },\n });\n}\n\nexport async function getShopWebhooks({ platform }: { platform: any }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"getWebhooksFunction\",\n args: {},\n });\n}\n\nexport async function handleShopOAuth({ platform, callbackUrl }: { platform: any; callbackUrl: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"oAuthFunction\",\n args: { callbackUrl },\n });\n}\n\nexport async function handleShopOAuthCallback({ platform, code, shop, state, appKey, appSecret, redirectUri }: { platform: any; code?: string; shop?: string; state?: string; appKey?: string; appSecret?: string; redirectUri?: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"oAuthCallbackFunction\",\n args: { code, shop, state, appKey, appSecret, redirectUri },\n });\n}\n\nexport async function handleShopOrderWebhook({ platform, event, headers }: { platform: any; event: any; headers: any }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"createOrderWebhookHandler\",\n args: { event, headers },\n });\n}\n\nexport async function handleShopCancelWebhook({ platform, event, headers }: { platform: any; event: any; headers: any }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"cancelOrderWebhookHandler\",\n args: { event, headers },\n });\n}\n\nexport async function addShopTracking({ platform, order, trackingCompany, trackingNumber }: { platform: any; order: any; trackingCompany: string; trackingNumber: string }) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"addTrackingFunction\",\n args: { order, trackingCompany, trackingNumber },\n });\n}", "// keystone.ts - Main entry point for Keystone\nimport config from './features/keystone';\n\nexport default config;", "import { createAuth } from \"@keystone-6/auth\";\nimport { config } from \"@keystone-6/core\";\nimport \"dotenv/config\";\nimport { models } from \"./models\";\nimport { extendGraphqlSchema } from \"./extendGraphqlSchema\";\nimport { permissionsList } from \"./models/fields\";\nimport { sendPasswordResetEmail } from \"./lib/mail\";\nimport Iron from \"@hapi/iron\";\nimport * as cookie from \"cookie\";\nimport { hashApiKeySync } from \"./lib/crypto-utils\";\nimport bcryptjs from \"bcryptjs\";\n\nconst databaseURL = process.env.DATABASE_URL || \"file:./keystone.db\";\n\nconst sessionConfig = {\n maxAge: 60 * 60 * 24 * 360, // How long they stay signed in?\n secret:\n process.env.SESSION_SECRET || \"this secret should only be used in testing\",\n};\n\nconst listKey = \"User\";\n\nexport function statelessSessions({\n secret,\n maxAge = 60 * 60 * 24 * 360,\n path = \"/\",\n secure = process.env.NODE_ENV === \"production\",\n ironOptions = Iron.defaults,\n domain,\n sameSite = \"lax\" as const,\n cookieName = \"keystonejs-session\",\n}: {\n secret: string;\n maxAge?: number;\n path?: string;\n secure?: boolean;\n ironOptions?: any;\n domain?: string;\n sameSite?: \"lax\" | \"none\" | \"strict\" | boolean;\n cookieName?: string;\n}) {\n if (!secret) {\n throw new Error(\"You must specify a session secret to use sessions\");\n }\n if (secret.length < 32) {\n throw new Error(\"The session secret must be at least 32 characters long\");\n }\n\n return {\n async get({ context }: { context: any }) {\n if (!context?.req) return;\n \n // Check for OAuth Bearer token authentication\n const authHeader = context.req.headers.authorization;\n \n if (authHeader?.startsWith(\"Bearer \")) {\n const accessToken = authHeader.replace(\"Bearer \", \"\");\n console.log('\uD83D\uDD11 ACCESS TOKEN:', accessToken);\n \n // Try to validate as API key first\n if (accessToken.startsWith(\"osp_\")) {\n console.log('\uD83D\uDD11 API KEY DETECTED, VALIDATING...');\n try {\n // Get all active API keys and test the token against each one\n const apiKeys = await context.sudo().query.ApiKey.findMany({\n where: { status: { equals: 'active' } },\n query: `\n id\n name\n scopes\n status\n expiresAt\n usageCount\n tokenSecret { isSet }\n user { id }\n `,\n });\n \n console.log('\uD83D\uDD11 CHECKING AGAINST', apiKeys.length, 'ACTIVE API KEYS');\n \n let matchingApiKey = null;\n \n // Test token against each API key using bcryptjs (same as Keystone's default KDF)\n for (const apiKey of apiKeys) {\n try {\n if (!apiKey.tokenSecret?.isSet) continue;\n \n // Get the full API key item with the tokenSecret value\n const fullApiKey = await context.sudo().db.ApiKey.findOne({\n where: { id: apiKey.id },\n });\n \n if (!fullApiKey || typeof fullApiKey.tokenSecret !== 'string') {\n continue;\n }\n \n // Use bcryptjs to compare - this is exactly what Keystone does internally\n const isValid = await bcryptjs.compare(accessToken, fullApiKey.tokenSecret);\n \n if (isValid) {\n matchingApiKey = apiKey;\n console.log('\uD83D\uDD11 FOUND MATCHING API KEY:', apiKey.id);\n break;\n }\n } catch (error) {\n console.log('\uD83D\uDD11 ERROR VERIFYING API KEY:', error);\n // Continue to next API key if this one doesn't match\n continue;\n }\n }\n \n if (!matchingApiKey) {\n console.log('\uD83D\uDD11 NO MATCHING API KEY FOUND');\n return; // API key not found or invalid\n }\n \n if (matchingApiKey.status !== 'active') {\n console.log('\uD83D\uDD11 API KEY NOT ACTIVE:', matchingApiKey.status);\n return; // API key is inactive\n }\n \n if (matchingApiKey.expiresAt && new Date() > new Date(matchingApiKey.expiresAt)) {\n console.log('\uD83D\uDD11 API KEY EXPIRED');\n // Auto-revoke expired keys\n await context.sudo().query.ApiKey.updateOne({\n where: { id: matchingApiKey.id },\n data: { status: 'revoked' },\n });\n return; // API key has expired\n }\n \n // Update usage statistics (async, don't wait)\n const today = new Date().toISOString().split('T')[0];\n const usage = matchingApiKey.usageCount || { total: 0, daily: {} };\n usage.total = (usage.total || 0) + 1;\n usage.daily[today] = (usage.daily[today] || 0) + 1;\n \n context.sudo().query.ApiKey.updateOne({\n where: { id: matchingApiKey.id },\n data: {\n lastUsedAt: new Date(),\n usageCount: usage,\n },\n }).catch(console.error);\n \n // Return user session with API key scopes attached\n if (matchingApiKey.user?.id) {\n const session = { \n itemId: matchingApiKey.user.id, \n listKey,\n apiKeyScopes: matchingApiKey.scopes || [] // Attach scopes for permission checking\n };\n console.log('\uD83D\uDD11 RETURNING SESSION:', JSON.stringify(session, null, 2));\n return session;\n }\n } catch (err) {\n console.log('\uD83D\uDD11 API Key validation error:', err);\n return;\n }\n }\n \n // If not API key, try as regular session token\n try {\n return await Iron.unseal(accessToken, secret, ironOptions);\n } catch (err) {}\n }\n \n // Check for session cookie\n const cookies = cookie.parse(context.req.headers.cookie || \"\");\n const token = cookies[cookieName];\n if (!token) return;\n try {\n return await Iron.unseal(token, secret, ironOptions);\n } catch (err) {}\n },\n async end({ context }: { context: any }) {\n if (!context?.res) return;\n\n context.res.setHeader(\n \"Set-Cookie\",\n cookie.serialize(cookieName, \"\", {\n maxAge: 0,\n expires: new Date(),\n httpOnly: true,\n secure,\n path,\n sameSite,\n domain,\n })\n );\n },\n async start({ context, data }: { context: any; data: any }) {\n if (!context?.res) return;\n\n const sealedData = await Iron.seal(data, secret, {\n ...ironOptions,\n ttl: maxAge * 1000,\n });\n context.res.setHeader(\n \"Set-Cookie\",\n cookie.serialize(cookieName, sealedData, {\n maxAge,\n expires: new Date(Date.now() + maxAge * 1000),\n httpOnly: true,\n secure,\n path,\n sameSite,\n domain,\n })\n );\n\n return sealedData;\n },\n };\n}\n\nconst { withAuth } = createAuth({\n listKey,\n identityField: \"email\",\n secretField: \"password\",\n initFirstItem: {\n fields: [\"name\", \"email\", \"password\"],\n itemData: {\n role: {\n create: {\n name: \"Admin\",\n canSeeOtherUsers: true,\n canEditOtherUsers: true,\n canManageUsers: true,\n canManageRoles: true,\n canAccessDashboard: true,\n canSeeOtherShops: true,\n canManageShops: true,\n canCreateShops: true,\n canSeeOtherChannels: true,\n canManageChannels: true,\n canCreateChannels: true,\n canSeeOtherOrders: true,\n canManageOrders: true,\n canProcessOrders: true,\n canSeeOtherMatches: true,\n canManageMatches: true,\n canCreateMatches: true,\n canSeeOtherLinks: true,\n canManageLinks: true,\n canCreateLinks: true,\n canManagePlatforms: true,\n canViewPlatformMetrics: true,\n canManageApiKeys: true,\n canCreateApiKeys: true,\n canAccessAnalytics: true,\n canExportData: true,\n canManageWebhooks: true,\n },\n },\n },\n },\n passwordResetLink: {\n async sendToken(args) {\n // send the email\n await sendPasswordResetEmail(args.token, args.identity);\n },\n },\n sessionData: `id name email role { id name ${permissionsList.join(\" \")} }`,\n});\n\nexport default withAuth(\n config({\n db: {\n provider: \"postgresql\",\n url: databaseURL,\n },\n lists: models,\n ui: {\n isAccessAllowed: ({ session }) => session?.data.role?.canAccessDashboard ?? false,\n },\n session: statelessSessions(sessionConfig),\n graphql: {\n extendGraphqlSchema,\n },\n })\n);", "import { list } from \"@keystone-6/core\";\nimport { allOperations, denyAll } from \"@keystone-6/core/access\";\nimport {\n checkbox,\n password,\n relationship,\n text,\n timestamp,\n} from \"@keystone-6/core/fields\";\n\nimport {\n isSignedIn,\n permissions,\n rules,\n itemRules,\n fieldRules,\n} from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const User = list({\n access: {\n operation: {\n query: isSignedIn,\n create: permissions.canManageUsers,\n update: isSignedIn,\n delete: permissions.canManageUsers,\n },\n filter: {\n query: rules.canReadPeople,\n update: rules.canUpdatePeople,\n delete: rules.canUpdatePeople,\n },\n item: {\n update: itemRules.canUpdateUser,\n delete: itemRules.canDeleteUser,\n },\n },\n ui: {\n hideCreate: (args: any) => !permissions.canManageUsers({ session: args.session, context: args.context, listKey: 'User', operation: 'create' }),\n hideDelete: (args: any) => !permissions.canManageUsers({ session: args.session, context: args.context, listKey: 'User', operation: 'delete' }),\n listView: {\n initialColumns: [\"name\", \"email\", \"role\", \"shops\", \"channels\"],\n },\n itemView: {\n defaultFieldMode: ({ session, item }) => {\n // canEditOtherUsers can edit other people\n if (session?.data.role?.canEditOtherUsers) return \"edit\";\n\n // edit themselves\n if (session?.itemId === item?.id) return \"edit\";\n\n // else, default all fields to read mode\n return \"read\";\n },\n },\n },\n fields: {\n name: text({\n validation: {\n isRequired: true,\n },\n }),\n email: text({\n isFilterable: false,\n isOrderable: false,\n isIndexed: \"unique\",\n validation: {\n isRequired: true,\n },\n }),\n password: password({\n access: {\n read: fieldRules.canReadUserPassword,\n update: fieldRules.canUpdateUserPassword,\n },\n validation: { isRequired: true },\n }),\n role: relationship({\n ref: \"Role.assignedTo\",\n access: {\n create: fieldRules.canManageUserRole,\n update: fieldRules.canManageUserRole,\n },\n ui: {\n itemView: {\n fieldMode: (args: any) =>\n permissions.canManageUsers({ session: args.session, context: args.context, listKey: 'User', operation: 'update' }) ? \"edit\" : \"read\",\n },\n },\n }),\n\n // E-commerce Platform Management Relationships\n shops: relationship({\n ref: \"Shop.user\",\n many: true,\n }),\n channels: relationship({\n ref: \"Channel.user\",\n many: true,\n }),\n orders: relationship({\n ref: \"Order.user\",\n many: true,\n }),\n lineItems: relationship({\n ref: \"LineItem.user\",\n many: true,\n }),\n cartItems: relationship({\n ref: \"CartItem.user\",\n many: true,\n }),\n shopItems: relationship({\n ref: \"ShopItem.user\",\n many: true,\n }),\n channelItems: relationship({\n ref: \"ChannelItem.user\",\n many: true,\n }),\n matches: relationship({\n ref: \"Match.user\",\n many: true,\n }),\n links: relationship({\n ref: \"Link.user\",\n many: true,\n }),\n trackingDetails: relationship({\n ref: \"TrackingDetail.user\",\n many: true,\n }),\n shopPlatforms: relationship({\n ref: \"ShopPlatform.user\",\n many: true,\n }),\n channelPlatforms: relationship({\n ref: \"ChannelPlatform.user\",\n many: true,\n }),\n apiKeys: relationship({\n ref: \"ApiKey.user\",\n many: true,\n }),\n\n ...trackingFields,\n },\n});\n", "/**\n * API Key Scopes to Permission Mapping\n * \n * This file maps API key scopes (used by external integrations) to internal permissions.\n * When an API key has a certain scope, it grants the mapped permissions.\n */\n\nimport type { ApiKeyScope } from '../models/ApiKey';\n\nexport type OpenseaPermission = \n | \"canSeeOtherUsers\"\n | \"canEditOtherUsers\"\n | \"canManageUsers\"\n | \"canManageRoles\"\n | \"canAccessDashboard\"\n | \"canSeeOtherShops\"\n | \"canManageShops\"\n | \"canCreateShops\"\n | \"canSeeOtherChannels\"\n | \"canManageChannels\"\n | \"canCreateChannels\"\n | \"canSeeOtherOrders\"\n | \"canManageOrders\"\n | \"canProcessOrders\"\n | \"canSeeOtherMatches\"\n | \"canManageMatches\"\n | \"canCreateMatches\"\n | \"canSeeOtherLinks\"\n | \"canManageLinks\"\n | \"canCreateLinks\"\n | \"canManagePlatforms\"\n | \"canViewPlatformMetrics\"\n | \"canManageApiKeys\"\n | \"canCreateApiKeys\"\n | \"canAccessAnalytics\"\n | \"canExportData\"\n | \"canManageWebhooks\";\n\n/**\n * Maps API key scopes to internal permissions\n */\nexport const SCOPE_TO_PERMISSIONS: Record = {\n // Orders\n \"read_orders\": [\"canSeeOtherOrders\"],\n \"write_orders\": [\"canSeeOtherOrders\", \"canManageOrders\", \"canProcessOrders\"],\n \n // Products (these don't have direct permissions but follow the pattern)\n \"read_products\": [],\n \"write_products\": [],\n \n // Shops\n \"read_shops\": [\"canSeeOtherShops\"],\n \"write_shops\": [\"canSeeOtherShops\", \"canManageShops\", \"canCreateShops\"],\n \n // Channels\n \"read_channels\": [\"canSeeOtherChannels\"],\n \"write_channels\": [\"canSeeOtherChannels\", \"canManageChannels\", \"canCreateChannels\"],\n \n // Matches\n \"read_matches\": [\"canSeeOtherMatches\"],\n \"write_matches\": [\"canSeeOtherMatches\", \"canManageMatches\", \"canCreateMatches\"],\n \n // Links\n \"read_links\": [\"canSeeOtherLinks\"],\n \"write_links\": [\"canSeeOtherLinks\", \"canManageLinks\", \"canCreateLinks\"],\n \n // Platforms\n \"read_platforms\": [\"canViewPlatformMetrics\"],\n \"write_platforms\": [\"canViewPlatformMetrics\", \"canManagePlatforms\"],\n \n // Webhooks\n \"read_webhooks\": [\"canManageWebhooks\"], // Read webhooks requires manage permission\n \"write_webhooks\": [\"canManageWebhooks\"],\n \n // Analytics\n \"read_analytics\": [\"canAccessAnalytics\", \"canExportData\"],\n \n // Users\n \"read_users\": [\"canSeeOtherUsers\"],\n \"write_users\": [\"canSeeOtherUsers\", \"canEditOtherUsers\", \"canManageUsers\", \"canManageRoles\"],\n};\n\n/**\n * Gets all permissions for a given set of API key scopes\n */\nexport function getPermissionsForApiKeyScopes(scopes: ApiKeyScope[]): OpenseaPermission[] {\n const permissions = new Set();\n \n scopes.forEach(scope => {\n const scopePermissions = SCOPE_TO_PERMISSIONS[scope];\n if (scopePermissions) {\n scopePermissions.forEach(permission => permissions.add(permission));\n }\n });\n \n return Array.from(permissions);\n}\n\n/**\n * Checks if a set of API key scopes grants a specific permission\n */\nexport function hasApiKeyPermission(scopes: ApiKeyScope[], permission: OpenseaPermission): boolean {\n return getPermissionsForApiKeyScopes(scopes).includes(permission);\n}\n\n/**\n * Helper function to check if API key scopes grant a permission\n */\nexport function checkApiKeyPermission(session: any, permission: OpenseaPermission): boolean {\n if (!session?.apiKeyScopes) return false;\n \n const scopes = session.apiKeyScopes as ApiKeyScope[];\n return hasApiKeyPermission(scopes, permission);\n}", "// Keystone 6 Access Control - Following Official Documentation\n// https://keystonejs.com/docs/config/access-control\n\nimport { checkApiKeyPermission, type OpenseaPermission } from './lib/api-key-scopes';\n\nexport type Session = {\n itemId: string\n listKey: string\n data: {\n id: string\n name: string\n email: string\n role: {\n id: string\n name: string\n // Basic Dashboard Permissions\n canSeeOtherUsers: boolean\n canEditOtherUsers: boolean\n canManageUsers: boolean\n canManageRoles: boolean\n canAccessDashboard: boolean\n \n // E-commerce Platform Permissions\n // Shop Management\n canSeeOtherShops: boolean\n canManageShops: boolean\n canCreateShops: boolean\n \n // Channel Management\n canSeeOtherChannels: boolean\n canManageChannels: boolean\n canCreateChannels: boolean\n \n // Order Management\n canSeeOtherOrders: boolean\n canManageOrders: boolean\n canProcessOrders: boolean\n \n // Product & Inventory Management\n canSeeOtherMatches: boolean\n canManageMatches: boolean\n canCreateMatches: boolean\n \n // Linking System\n canSeeOtherLinks: boolean\n canManageLinks: boolean\n canCreateLinks: boolean\n \n // Platform Integration\n canManagePlatforms: boolean\n canViewPlatformMetrics: boolean\n \n // API Key Management\n canManageApiKeys: boolean\n canCreateApiKeys: boolean\n \n // Advanced Features\n canAccessAnalytics: boolean\n canExportData: boolean\n canManageWebhooks: boolean\n }\n }\n}\n\n// Standard Keystone Access Control Arguments\ntype OperationAccessArgs = {\n session?: Session\n context: any\n listKey: string\n operation: string\n}\n\ntype FilterAccessArgs = {\n session?: Session\n context: any\n listKey: string\n operation: string\n}\n\ntype ItemAccessArgs = {\n session?: Session\n context: any\n listKey: string\n operation: string\n inputData?: any\n item?: any\n}\n\ntype FieldAccessArgs = {\n session?: Session\n context: any\n listKey: string\n fieldKey: string\n operation: string\n inputData?: any\n item?: any\n}\n\n// Basic Authentication Check\nexport const isSignedIn = ({ session }: OperationAccessArgs): boolean => {\n return Boolean(session)\n}\n\n// Helper function to check if API key scopes or role grants a permission\nfunction hasPermission(session: any, permission: OpenseaPermission): boolean {\n // If this is an API key session, ONLY check API key scopes\n if (session?.apiKeyScopes) {\n return checkApiKeyPermission(session, permission);\n }\n // Otherwise, check role-based permissions for regular user sessions\n return Boolean(session?.data?.role?.[permission]);\n}\n\n// Permission Functions - Operation Level Access Control\nexport const permissions = {\n // Basic Dashboard Permissions\n canSeeOtherUsers: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canSeeOtherUsers),\n \n canEditOtherUsers: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canEditOtherUsers),\n \n canManageUsers: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageUsers),\n \n canManageRoles: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageRoles),\n \n canAccessDashboard: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canAccessDashboard),\n \n // E-commerce Platform Permissions\n // Shop Management\n canSeeOtherShops: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canSeeOtherShops\"),\n \n canManageShops: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canManageShops\"),\n \n canCreateShops: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canCreateShops\"),\n \n // Channel Management\n canSeeOtherChannels: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canSeeOtherChannels\"),\n \n canManageChannels: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canManageChannels\"),\n \n canCreateChannels: ({ session }: OperationAccessArgs): boolean => \n hasPermission(session, \"canCreateChannels\"),\n \n canUpdateChannels: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageChannels),\n \n // Order Management\n canSeeOtherOrders: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canSeeOtherOrders),\n \n canManageOrders: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageOrders),\n \n canProcessOrders: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canProcessOrders),\n \n // Product & Inventory Management\n canSeeOtherMatches: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canSeeOtherMatches),\n \n canManageMatches: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageMatches),\n \n canCreateMatches: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canCreateMatches),\n \n // Linking System\n canSeeOtherLinks: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canSeeOtherLinks),\n \n canManageLinks: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageLinks),\n \n canCreateLinks: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canCreateLinks),\n \n // Platform Integration\n canManagePlatforms: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManagePlatforms),\n \n canViewPlatformMetrics: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canViewPlatformMetrics),\n \n // API Key Management\n canManageApiKeys: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageApiKeys),\n \n canCreateApiKeys: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canCreateApiKeys),\n \n // Advanced Features\n canAccessAnalytics: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canAccessAnalytics),\n \n canExportData: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canExportData),\n \n canManageWebhooks: ({ session }: OperationAccessArgs): boolean => \n Boolean(session?.data.role?.canManageWebhooks),\n}\n\n// Filter Rules - Filter Level Access Control\nexport const rules = {\n // User Rules\n canReadPeople: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n\n // Admin can see all users\n if (session.data.role?.canSeeOtherUsers) return true\n\n // Users can only see themselves\n return { id: { equals: session.itemId } }\n },\n \n canUpdatePeople: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n\n // Admin can edit all users\n if (session.data.role?.canEditOtherUsers) return true\n\n // Users can only edit themselves\n return { id: { equals: session.itemId } }\n },\n \n // E-commerce Multi-tenant Rules\n // Shop Rules - users can only access their own shops unless they have permission\n canReadShops: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all shops\n if (session.data.role?.canSeeOtherShops) return true\n \n // Users can only see their own shops\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageShops: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all shops\n if (session.data.role?.canManageShops) return true\n \n // Users can only manage their own shops\n return { user: { id: { equals: session.itemId } } }\n },\n \n // Channel Rules\n canReadChannels: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all channels\n if (session.data.role?.canSeeOtherChannels) return true\n \n // Users can only see their own channels\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageChannels: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all channels\n if (session.data.role?.canManageChannels) return true\n \n // Users can only manage their own channels\n return { user: { id: { equals: session.itemId } } }\n },\n \n canUpdateChannels: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can update all channels\n if (session.data.role?.canManageChannels) return true\n \n // Users can only update their own channels\n return { user: { id: { equals: session.itemId } } }\n },\n \n // Order Rules\n canReadOrders: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all orders\n if (session.data.role?.canSeeOtherOrders) return true\n \n // Users can only see their own orders\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageOrders: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all orders\n if (session.data.role?.canManageOrders) return true\n \n // Users can only manage their own orders\n return { user: { id: { equals: session.itemId } } }\n },\n \n // Match Rules (Product Matching)\n canReadMatches: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all matches\n if (session.data.role?.canSeeOtherMatches) return true\n \n // Users can only see their own matches\n return { user: { id: { equals: session.itemId } } }\n },\n \n canUpdateMatches: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all matches\n if (session.data.role?.canManageMatches) return true\n \n // Users can only manage their own matches\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageMatches: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all matches\n if (session.data.role?.canManageMatches) return true\n \n // Users can only manage their own matches\n return { user: { id: { equals: session.itemId } } }\n },\n \n // Link Rules (Shop-Channel Linking)\n canReadLinks: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all links\n if (session.data.role?.canSeeOtherLinks) return true\n \n // Users can only see their own links\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageLinks: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all links\n if (session.data.role?.canManageLinks) return true\n \n // Users can only manage their own links\n return { user: { id: { equals: session.itemId } } }\n },\n\n // API Key Rules\n canReadApiKeys: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can see all API keys\n if (session.data.role?.canManageApiKeys) return true\n \n // Users can only see their own API keys\n return { user: { id: { equals: session.itemId } } }\n },\n \n canManageApiKeys: ({ session }: FilterAccessArgs) => {\n if (!session) return false\n \n // Admin can manage all API keys\n if (session.data.role?.canManageApiKeys) return true\n \n // Users can only manage their own API keys\n return { user: { id: { equals: session.itemId } } }\n },\n}\n\n// Item-Level Access Control Functions\nexport const itemRules = {\n canUpdateUser: ({ session, item }: ItemAccessArgs): boolean => {\n if (!session) return false\n \n // Admin can edit any user\n if (session.data.role?.canEditOtherUsers) return true\n \n // Users can only edit themselves\n return session.itemId === item.id\n },\n \n canDeleteUser: ({ session }: ItemAccessArgs): boolean => {\n if (!session) return false\n \n // Only admin can delete users\n return Boolean(session.data.role?.canManageUsers)\n },\n}\n\n// Field-Level Access Control Functions\nexport const fieldRules = {\n canReadUserPassword: (): boolean => false, // Never allow reading passwords\n \n canUpdateUserPassword: ({ session, item }: FieldAccessArgs): boolean => {\n if (!session) return false\n \n // Admin can update any password\n if (session.data.role?.canManageUsers) return true\n \n // Users can only update their own password\n return session.itemId === item?.id\n },\n \n canManageUserRole: ({ session }: FieldAccessArgs): boolean => {\n if (!session) return false\n \n // Only admin can manage roles\n return Boolean(session.data.role?.canManageUsers)\n },\n}", "import { timestamp } from \"@keystone-6/core/fields\";\n\nexport const trackingFields = {\n createdAt: timestamp({\n access: { read: () => true, create: () => false, update: () => false },\n validation: { isRequired: true },\n defaultValue: { kind: \"now\" },\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n },\n hooks: {\n resolveInput: ({ context, operation, resolvedData }) => {\n if (operation === \"create\") return new Date();\n return resolvedData.createdAt;\n },\n },\n }),\n updatedAt: timestamp({\n access: { read: () => true, create: () => false, update: () => false },\n // db: { updatedAt: true },\n validation: { isRequired: true },\n defaultValue: { kind: \"now\" },\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n },\n hooks: {\n resolveInput: ({ context, operation, resolvedData }) => {\n if (operation === \"update\") return new Date();\n return resolvedData.updatedAt;\n },\n },\n }),\n};", "import {\n text,\n password,\n relationship,\n multiselect,\n select,\n timestamp,\n json,\n} from \"@keystone-6/core/fields\";\nimport { list } from \"@keystone-6/core\";\nimport { isSignedIn, rules, permissions } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { generateApiKeyTokenSync, hashApiKeySync } from \"../lib/crypto-utils\";\n\n// Define available API key scopes (using underscore format like OpenFront)\nexport const API_KEY_SCOPES = {\n // Orders\n \"read_orders\": \"View orders\",\n \"write_orders\": \"Manage orders\",\n \n // Products \n \"read_products\": \"View products\",\n \"write_products\": \"Manage products\",\n \n // Shops\n \"read_shops\": \"View shops\", \n \"write_shops\": \"Manage shops\",\n \n // Channels\n \"read_channels\": \"View channels\",\n \"write_channels\": \"Manage channels\",\n \n // Matches\n \"read_matches\": \"View product matches\",\n \"write_matches\": \"Manage product matches\",\n \n // Links\n \"read_links\": \"View automation links\",\n \"write_links\": \"Manage automation links\",\n \n // Platforms\n \"read_platforms\": \"View platform configurations\",\n \"write_platforms\": \"Manage platform configurations\",\n \n // Webhooks\n \"read_webhooks\": \"View webhook configurations\",\n \"write_webhooks\": \"Manage webhook configurations\",\n \n // Analytics\n \"read_analytics\": \"View analytics data\",\n \n // Users\n \"read_users\": \"View users\",\n \"write_users\": \"Manage users and permissions\",\n} as const;\n\nexport type ApiKeyScope = keyof typeof API_KEY_SCOPES;\n\n// Generate secure API key token\nfunction generateApiKeyToken(): string {\n return generateApiKeyTokenSync();\n}\n\n// Hash API key for secure storage\nfunction hashApiKey(key: string): string {\n return hashApiKeySync(key);\n}\n\nexport const ApiKey = list({\n access: {\n operation: {\n query: isSignedIn,\n create: permissions.canCreateApiKeys,\n update: permissions.canManageApiKeys,\n delete: permissions.canManageApiKeys,\n },\n filter: {\n query: rules.canReadApiKeys,\n update: rules.canManageApiKeys,\n delete: rules.canManageApiKeys,\n },\n },\n hooks: {\n validate: {\n create: async ({ resolvedData, addValidationError }) => {\n if (!resolvedData.scopes || resolvedData.scopes.length === 0) {\n addValidationError('At least one scope is required for API keys');\n }\n },\n },\n resolveInput: {\n create: async ({ resolvedData, context }) => {\n // Auto-assign user relationship\n return {\n ...resolvedData,\n user: resolvedData.user || (context.session?.itemId ? { connect: { id: context.session.itemId } } : undefined),\n };\n },\n },\n },\n fields: {\n name: text({\n validation: { isRequired: true },\n ui: {\n description: \"A descriptive name for this API key (e.g. 'Production Bot', 'Analytics Dashboard')\",\n },\n }),\n \n tokenSecret: password({\n validation: { isRequired: true },\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"hidden\" },\n listView: { fieldMode: \"hidden\" },\n description: \"Secure API key token (hashed and never displayed)\",\n },\n }),\n \n tokenPreview: text({\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n listView: { fieldMode: \"read\" },\n description: \"Preview of the API key (actual key is hidden for security)\",\n },\n }),\n \n scopes: json({\n defaultValue: [],\n ui: {\n description: \"Array of scopes for this API key. Available scopes: orders:read, orders:write, shops:read, shops:write, channels:read, channels:write, etc.\",\n },\n }),\n \n status: select({\n type: 'enum',\n options: [\n { label: \"Active\", value: \"active\" },\n { label: \"Inactive\", value: \"inactive\" },\n { label: \"Revoked\", value: \"revoked\" },\n ],\n defaultValue: \"active\",\n ui: {\n description: \"Current status of this API key\",\n },\n }),\n \n expiresAt: timestamp({\n ui: {\n description: \"When this API key expires (optional - leave blank for no expiration)\",\n },\n }),\n \n lastUsedAt: timestamp({\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n description: \"Last time this API key was used\",\n },\n }),\n \n usageCount: json({\n defaultValue: { total: 0, daily: {} },\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n description: \"Usage statistics for this API key\",\n },\n }),\n \n restrictedToIPs: json({\n defaultValue: [],\n ui: {\n description: \"Optional: Restrict this key to specific IP addresses (array of IPs)\",\n },\n }),\n \n user: relationship({\n ref: \"User.apiKeys\",\n ui: {\n createView: { fieldMode: \"hidden\" },\n itemView: { fieldMode: \"read\" },\n },\n }),\n \n ...trackingFields,\n },\n \n ui: {\n labelField: \"name\",\n listView: {\n initialColumns: [\"name\", \"tokenPreview\", \"scopes\", \"status\", \"lastUsedAt\", \"expiresAt\"],\n },\n description: \"Secure API keys for programmatic access to Openship\",\n },\n});\n\n// Helper function to validate API key tokens using password field\nexport async function validateApiKeyToken(\n apiKeyId: string,\n token: string,\n context: any\n): Promise {\n try {\n // Use Keystone's built-in password verification through createAuth\n // This is a simplified approach - we'll handle this in the authentication layer\n const result = await context.query.ApiKey.authenticateItemWithPassword({\n identifier: apiKeyId,\n secret: token,\n identityField: 'id',\n secretField: 'tokenSecret'\n });\n \n return result.success;\n } catch (error) {\n return false;\n }\n}\n\n// Simplified validation function for API keys\nexport async function validateApiKey(\n token: string,\n requiredScopes: ApiKeyScope[] = [],\n context: any\n): Promise<{\n valid: boolean;\n user?: any;\n scopes?: ApiKeyScope[];\n error?: string;\n}> {\n if (!token || !token.startsWith('osp_')) {\n return { valid: false, error: 'Invalid API key format' };\n }\n \n // This will be handled differently - we'll need to update the keystone/index.ts\n // authentication logic to use the password field directly\n // For now, return a placeholder that will be updated in the auth layer\n return { valid: false, error: 'API key validation moved to auth layer' };\n}\n\n// Scope validation helper\nexport function hasScope(userScopes: ApiKeyScope[], requiredScope: ApiKeyScope): boolean {\n // Check for specific scope\n return userScopes.includes(requiredScope);\n}\n\n// Check if user has any of the required scopes\nexport function hasAnyScope(userScopes: ApiKeyScope[], requiredScopes: ApiKeyScope[]): boolean {\n return requiredScopes.some(scope => hasScope(userScopes, scope));\n}\n\n// Map scopes to Openship permissions\nexport function getPermissionsForScopes(scopes: ApiKeyScope[]): string[] {\n const permissions = new Set();\n \n scopes.forEach(scope => {\n switch (scope) {\n case 'read_orders':\n permissions.add('canReadOrders');\n break;\n case 'write_orders':\n permissions.add('canReadOrders');\n permissions.add('canManageOrders');\n permissions.add('canProcessOrders');\n break;\n case 'read_products':\n // Add product read permissions\n break;\n case 'write_products':\n // Add product write permissions\n break;\n case 'read_shops':\n permissions.add('canReadShops');\n break;\n case 'write_shops':\n permissions.add('canReadShops');\n permissions.add('canManageShops');\n permissions.add('canCreateShops');\n break;\n case 'read_channels':\n permissions.add('canReadChannels');\n break;\n case 'write_channels':\n permissions.add('canReadChannels');\n permissions.add('canManageChannels');\n permissions.add('canCreateChannels');\n break;\n case 'read_users':\n permissions.add('canReadUsers');\n break;\n case 'write_users':\n permissions.add('canReadUsers');\n permissions.add('canManageUsers');\n permissions.add('canManageRoles');\n break;\n }\n });\n \n return Array.from(permissions);\n}", "import { relationship, text } from \"@keystone-6/core/fields\";\nimport { list } from \"@keystone-6/core\";\nimport { isSignedIn, permissions } from \"../access\";\nimport { permissionFields } from \"./fields\";\n\nexport const Role = list({\n /*\n SPEC\n - [x] Block all public access\n - [x] Restrict edit access based on canManageRoles\n - [ ] Prevent users from deleting their own role\n - [ ] Add a pre-save hook that ensures some permissions are selected when others are:\n - [ ] when canEditOtherUsers is true, canSeeOtherUsers must be true\n - [ ] when canManageUsers is true, canEditOtherUsers and canSeeOtherUsers must be true\n - [ ] Extend the Admin UI with client-side validation based on the same set of rules\n */\n access: {\n operation: {\n query: isSignedIn,\n create: permissions.canManageRoles,\n update: permissions.canManageRoles,\n delete: permissions.canManageRoles,\n },\n },\n ui: {\n hideCreate: (args: any) => !permissions.canManageRoles({ session: args.session, context: args.context, listKey: 'Role', operation: 'create' }),\n hideDelete: (args: any) => !permissions.canManageRoles({ session: args.session, context: args.context, listKey: 'Role', operation: 'delete' }),\n listView: {\n initialColumns: [\"name\", \"assignedTo\"],\n },\n itemView: {\n defaultFieldMode: (args: any) =>\n permissions.canManageRoles({ session: args.session, context: args.context, listKey: 'Role', operation: 'update' }) ? \"edit\" : \"read\",\n },\n },\n fields: {\n /* The name of the role */\n name: text({ validation: { isRequired: true } }),\n ...permissionFields,\n assignedTo: relationship({\n ref: \"User.role\",\n many: true,\n ui: {\n itemView: { fieldMode: \"read\" },\n },\n }),\n },\n});", "import { checkbox } from '@keystone-6/core/fields';\n\nexport const permissionFields = {\n canSeeOtherUsers: checkbox({\n label: 'User can query other users',\n }),\n canEditOtherUsers: checkbox({\n label: 'User can edit other users',\n }),\n canManageUsers: checkbox({\n label: 'User can CRUD users',\n }),\n canManageRoles: checkbox({\n label: 'User can CRUD roles',\n }),\n canAccessDashboard: checkbox({\n label: 'User can access the dashboard',\n }),\n canSeeOtherShops: checkbox({\n label: 'User can query other shops',\n }),\n canManageShops: checkbox({\n label: 'User can CRUD shops',\n }),\n canCreateShops: checkbox({\n label: 'User can create shops',\n }),\n canSeeOtherChannels: checkbox({\n label: 'User can query other channels',\n }),\n canManageChannels: checkbox({\n label: 'User can CRUD channels',\n }),\n canCreateChannels: checkbox({\n label: 'User can create channels',\n }),\n canSeeOtherOrders: checkbox({\n label: 'User can query other orders',\n }),\n canManageOrders: checkbox({\n label: 'User can CRUD orders',\n }),\n canProcessOrders: checkbox({\n label: 'User can process orders',\n }),\n canSeeOtherMatches: checkbox({\n label: 'User can query other matches',\n }),\n canManageMatches: checkbox({\n label: 'User can CRUD matches',\n }),\n canCreateMatches: checkbox({\n label: 'User can create matches',\n }),\n canSeeOtherLinks: checkbox({\n label: 'User can query other links',\n }),\n canManageLinks: checkbox({\n label: 'User can CRUD links',\n }),\n canCreateLinks: checkbox({\n label: 'User can create links',\n }),\n canManagePlatforms: checkbox({\n label: 'User can manage platforms',\n }),\n canViewPlatformMetrics: checkbox({\n label: 'User can view platform metrics',\n }),\n canManageApiKeys: checkbox({\n label: 'User can manage API keys',\n }),\n canCreateApiKeys: checkbox({\n label: 'User can create API keys',\n }),\n canAccessAnalytics: checkbox({\n label: 'User can access analytics',\n }),\n canExportData: checkbox({\n label: 'User can export data',\n }),\n canManageWebhooks: checkbox({\n label: 'User can manage webhooks',\n }),\n};\n\n// export type Permission = keyof typeof permissionFields;\n\nexport const permissionsList = Object.keys(\n permissionFields\n);", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport {\n checkbox,\n float,\n integer,\n json,\n relationship,\n text,\n timestamp,\n} from \"@keystone-6/core/fields\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { placeMultipleOrders } from \"../lib/placeMultipleOrders\";\nimport { getMatches } from \"../extendGraphqlSchema/mutations/addMatchToCart\";\n\nasync function applyDynamicWhereClause(context: any, linkId: string, orderId: string) {\n const link = await context.query.Link.findOne({\n where: { id: linkId },\n query: 'id dynamicWhereClause',\n });\n\n if (!link || !link.dynamicWhereClause) {\n return null;\n }\n\n const whereClause = {\n ...link.dynamicWhereClause,\n id: { equals: orderId },\n };\n\n const matchedOrder = await context.query.Order.findOne({\n where: whereClause,\n query: 'id',\n });\n\n return matchedOrder;\n}\n\nexport const Order = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageOrders,\n },\n filter: {\n query: rules.canReadOrders,\n update: rules.canManageOrders,\n delete: rules.canManageOrders,\n },\n },\n hooks: {\n resolveInput: {\n create: ({ operation, resolvedData, context }) => {\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n return {\n ...resolvedData,\n user: { connect: { id: context.session.itemId } },\n };\n }\n return resolvedData;\n },\n },\n afterOperation: async ({ operation, item, context }: any) => {\n if (operation === \"create\") {\n const sudoContext = context.sudo();\n\n const order = await sudoContext.query.Order.findOne({\n where: { id: item.id },\n query: `\n id\n user {\n id\n }\n shop {\n id\n name\n linkMode\n links {\n id\n rank\n channel {\n id\n name\n }\n }\n }\n lineItems {\n name\n price\n lineItemId\n quantity\n image\n productId\n variantId\n sku\n }\n cartItemsCount\n `,\n });\n\n if (item.linkOrder && order.shop?.links.length > 0) {\n const links = order.shop.links.sort((a: any, b: any) => a.rank - b.rank);\n let matchedLinks: any[] = [];\n\n if (order.shop.linkMode === 'sequential') {\n for (const link of links) {\n const matchedOrder = await applyDynamicWhereClause(sudoContext, link.id, order.id);\n if (matchedOrder) {\n matchedLinks.push(link);\n break;\n }\n }\n } else if (order.shop.linkMode === 'simultaneous') {\n for (const link of links) {\n const matchedOrder = await applyDynamicWhereClause(sudoContext, link.id, order.id);\n if (matchedOrder) {\n matchedLinks.push(link);\n }\n }\n }\n\n if (matchedLinks.length > 0) {\n for (const link of matchedLinks) {\n await sudoContext.query.CartItem.createMany({\n data: order.lineItems.map((c: any) => ({\n ...c,\n channel: { connect: { id: link.channel.id } },\n order: { connect: { id: item.id } },\n user: { connect: { id: order.user?.id } },\n })),\n });\n }\n\n if (item.processOrder) {\n await placeMultipleOrders({\n ids: [item.id],\n query: sudoContext.query,\n });\n }\n } else {\n await sudoContext.query.Order.updateOne({\n where: { id: item.id },\n data: {\n error: \"No matching link found for this order\",\n },\n });\n }\n } else if (item.matchOrder) {\n if (item.matchOrder) {\n try {\n const cartItemsFromMatch = await getMatches({\n orderId: item.id,\n context: sudoContext,\n });\n\n const order = await sudoContext.query.Order.findOne({\n where: { id: item.id },\n query: `id error`,\n });\n if (order?.error) {\n const updatedOrder = await sudoContext.query.Order.updateOne({\n where: { id: item.id },\n data: {\n status: \"PENDING\",\n },\n });\n } else {\n if (item.processOrder) {\n const processedOrder = await placeMultipleOrders({\n ids: [item.id],\n query: sudoContext.query,\n });\n }\n }\n } catch (matchError) {\n // Handle match errors gracefully - don't break order creation\n console.error('Error during match processing:', matchError);\n await sudoContext.query.Order.updateOne({\n where: { id: item.id },\n data: {\n error: `Match processing failed: ${matchError instanceof Error ? matchError.message : 'Unknown error'}`,\n status: \"PENDING\",\n },\n });\n }\n }\n } else if (order.cartItemsCount > 0 && item.processOrder) {\n // Process the order if there are cart items and processOrder is true\n const processedOrder = await placeMultipleOrders({\n ids: [item.id],\n query: sudoContext.query,\n });\n }\n }\n },\n },\n ui: {\n listView: {\n initialColumns: [\"orderId\", \"orderName\", \"email\", \"totalPrice\", \"shop\"],\n },\n },\n fields: {\n // Order identifiers\n orderId: text({\n isIndexed: \"unique\",\n validation: { isRequired: true },\n }),\n orderName: text(),\n email: text(),\n\n // Customer information\n firstName: text(),\n lastName: text(),\n streetAddress1: text(),\n streetAddress2: text(),\n city: text(),\n state: text(),\n zip: text(),\n country: text(),\n phone: text(),\n\n // Pricing\n currency: text(),\n totalPrice: float(),\n subTotalPrice: float(),\n totalDiscounts: float(),\n totalTax: float(),\n\n // Processing flags\n linkOrder: checkbox({ defaultValue: true }),\n matchOrder: checkbox({ defaultValue: true }),\n processOrder: checkbox({ defaultValue: true }),\n\n // Status tracking\n status: text({ defaultValue: \"PENDING\" }),\n error: text({\n ui: {\n displayMode: \"textarea\",\n },\n }),\n\n // Metadata\n orderMetadata: json(),\n\n // Relationships\n shop: relationship({\n ref: \"Shop.orders\",\n ui: {\n displayMode: \"cards\",\n cardFields: [\"name\", \"domain\"],\n inlineCreate: { fields: [\"name\", \"domain\"] },\n inlineEdit: { fields: [\"name\", \"domain\"] },\n },\n }),\n lineItems: relationship({\n ref: \"LineItem.order\",\n many: true,\n ui: {\n displayMode: \"cards\",\n cardFields: [\"name\", \"quantity\", \"price\"],\n inlineCreate: { fields: [\"name\", \"quantity\", \"price\"] },\n inlineEdit: { fields: [\"name\", \"quantity\", \"price\"] },\n },\n }),\n cartItems: relationship({\n ref: \"CartItem.order\",\n many: true,\n }),\n user: relationship({\n ref: \"User.orders\",\n }),\n\n ...trackingFields,\n },\n});\n", "interface Platform {\n [key: string]: any;\n searchProductsFunction: string;\n getProductFunction: string;\n createPurchaseFunction: string;\n createWebhookFunction: string;\n deleteWebhookFunction: string;\n getWebhooksFunction: string;\n oAuthFunction: string;\n oAuthCallbackFunction: string;\n createTrackingWebhookHandler: string;\n cancelPurchaseWebhookHandler: string;\n}\n\nexport async function executeChannelAdapterFunction({\n platform,\n functionName,\n args,\n}: {\n platform: Platform;\n functionName: string;\n args: any;\n}) {\n const functionPath = platform[functionName];\n\n if (functionPath.startsWith('http')) {\n const response = await fetch(functionPath, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ platform, ...args }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP request failed: ${response.statusText}`);\n }\n return response.json();\n }\n\n const adapter = await import(\n `../../integrations/channel/${functionPath}.ts`\n );\n\n const fn = adapter[functionName];\n if (!fn) {\n throw new Error(\n `Function ${functionName} not found in adapter ${functionPath}`,\n );\n }\n\n try {\n return await fn({ platform, ...args });\n } catch (error: any) {\n throw new Error(\n `Error executing ${functionName} for platform ${functionPath}: ${error.message}`,\n );\n }\n}\n\n// Helper functions for common channel operations\nexport async function searchChannelProducts({\n platform,\n searchEntry,\n after,\n}: {\n platform: Platform;\n searchEntry: string;\n after?: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'searchProductsFunction',\n args: { searchEntry, after },\n });\n}\n\nexport async function getChannelProduct({\n platform,\n productId,\n variantId,\n}: {\n platform: Platform;\n productId: string;\n variantId?: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'getProductFunction',\n args: { productId, variantId },\n });\n}\n\nexport async function createChannelPurchase({\n platform,\n cartItems,\n shipping,\n notes,\n}: {\n platform: Platform;\n cartItems: any[];\n shipping: any;\n notes: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'createPurchaseFunction',\n args: { cartItems, shipping, notes },\n });\n}\n\nexport async function createChannelWebhook({\n platform,\n endpoint,\n events,\n}: {\n platform: Platform;\n endpoint: string;\n events: any[];\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'createWebhookFunction',\n args: { endpoint, events },\n });\n}\n\nexport async function deleteChannelWebhook({\n platform,\n webhookId,\n}: {\n platform: Platform;\n webhookId: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'deleteWebhookFunction',\n args: { webhookId },\n });\n}\n\nexport async function getChannelWebhooks({ platform }: { platform: Platform }) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'getWebhooksFunction',\n args: {},\n });\n}\n\nexport async function handleChannelOAuth({\n platform,\n callbackUrl,\n}: {\n platform: Platform;\n callbackUrl: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'oAuthFunction',\n args: { callbackUrl },\n });\n}\n\nexport async function handleChannelOAuthCallback({\n platform,\n code,\n shop,\n state,\n}: {\n platform: Platform;\n code: string;\n shop: string;\n state: string;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'oAuthCallbackFunction',\n args: { code, shop, state },\n });\n}\n\nexport async function handleChannelTrackingWebhook({\n platform,\n event,\n headers,\n}: {\n platform: Platform;\n event: any;\n headers: any;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'createTrackingWebhookHandler',\n args: { event, headers },\n });\n}\n\nexport async function handleChannelCancelWebhook({\n platform,\n event,\n headers,\n}: {\n platform: Platform;\n event: any;\n headers: any;\n}) {\n return executeChannelAdapterFunction({\n platform,\n functionName: 'cancelPurchaseWebhookHandler',\n args: { event, headers },\n });\n}", "export async function executeShopAdapterFunction({ platform, functionName, args }: any) {\n const functionPath = platform[functionName];\n\n if (functionPath.startsWith(\"http\")) {\n const response = await fetch(functionPath, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ platform, ...args }),\n });\n\n if (!response.ok) {\n throw new Error(`HTTP request failed: ${response.statusText}`);\n }\n \n const result = await response.json();\n return result;\n }\n\n const adapter = await import(\n `../../integrations/shop/${functionPath}.ts`\n );\n\n const fn = adapter[functionName];\n if (!fn) {\n throw new Error(\n `Function ${functionName} not found in adapter ${functionPath}`\n );\n }\n\n try {\n const result = await fn({ platform, ...args });\n return result;\n } catch (error) {\n throw new Error(\n `Error executing ${functionName} for platform ${functionPath}: ${(error as any)?.message || 'Unknown error'}`\n );\n }\n}\n\n// Helper functions for common shop operations\nexport async function searchShopProducts({ platform, searchEntry, after }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"searchProductsFunction\",\n args: { searchEntry, after },\n });\n}\n\nexport async function getShopProduct({ platform, productId, variantId }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"getProductFunction\",\n args: { productId, variantId },\n });\n}\n\nexport async function searchShopOrders({ platform, searchEntry, after }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"searchOrdersFunction\",\n args: { searchEntry, after },\n });\n}\n\nexport async function updateShopProduct({ platform, productId, variantId, inventory, price }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"updateProductFunction\",\n args: { productId, variantId, inventory, price },\n });\n}\n\nexport async function addCartToPlatformOrder({ platform, cartItems, orderId }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"addCartToPlatformOrderFunction\",\n args: { cartItems, orderId },\n });\n}\n\nexport async function createShopWebhook({ platform, endpoint, events }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"createWebhookFunction\",\n args: { endpoint, events },\n });\n}\n\nexport async function deleteShopWebhook({ platform, webhookId }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"deleteWebhookFunction\",\n args: { webhookId },\n });\n}\n\nexport async function getShopWebhooks({ platform }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"getWebhooksFunction\",\n args: {},\n });\n}\n\nexport async function handleShopOAuth({ platform, callbackUrl }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"oAuthFunction\",\n args: { callbackUrl },\n });\n}\n\nexport async function handleShopOAuthCallback({ platform, code, shop, state }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"oAuthCallbackFunction\",\n args: { code, shop, state },\n });\n}\n\nexport async function handleShopOrderWebhook({ platform, event, headers }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"createOrderWebhookHandler\",\n args: { event, headers },\n });\n}\n\nexport async function handleShopCancelWebhook({ platform, event, headers }: any) {\n return executeShopAdapterFunction({\n platform,\n functionName: \"cancelOrderWebhookHandler\",\n args: { event, headers },\n });\n}", "import { createChannelPurchase } from \"../utils/channelProviderAdapter\";\nimport { addCartToPlatformOrder } from \"../utils/shopProviderAdapter\";\n\nasync function updateCartItems({\n query,\n cartItems,\n url = \"\",\n error = \"\",\n purchaseId = \"\",\n}: {\n query: any;\n cartItems: Array<{ id: string }>;\n url?: string;\n error?: string;\n purchaseId?: string;\n}) {\n const update = [];\n for (const { id } of cartItems) {\n const res = await query.CartItem.updateOne({\n where: {\n id,\n },\n data: {\n url,\n error,\n purchaseId,\n },\n });\n update.push(res);\n }\n return update;\n}\n\nexport async function placeMultipleOrders({ ids, query }: { ids: string[]; query: any }) {\n const processed = [];\n for (const orderId of ids) {\n const {\n firstName,\n lastName,\n streetAddress1,\n streetAddress2,\n city,\n state,\n zip,\n country,\n phone,\n currency,\n user,\n shop,\n orderId: shopOrderId,\n orderName,\n } = await query.Order.findOne({\n where: {\n id: orderId,\n },\n query: `\n firstName,\n lastName,\n streetAddress1,\n streetAddress2,\n city,\n state,\n zip,\n country,\n phone,\n currency\n shop {\n domain\n accessToken\n platform {\n addCartToPlatformOrderFunction\n }\n }\n orderId\n orderName\n user {\n email\n }\n `,\n });\n\n const cartChannels = await query.Channel.findMany({\n query: `\n domain\n accessToken\n cartItems(\n where: {\n order: { id: { equals: \"${orderId}\" }}\n purchaseId: { equals: \"\" }\n url: { equals: \"\" }\n }\n ) {\n id\n productId\n variantId\n sku\n name\n quantity\n price\n } \n platform {\n createPurchaseFunction\n }\n metadata\n `,\n });\n\n for (const {\n domain,\n accessToken,\n cartItems,\n platform,\n metadata,\n } of cartChannels.filter((channel: any) => channel.cartItems.length > 0)) {\n const body = {\n domain,\n accessToken,\n cartItems,\n address: {\n firstName,\n lastName,\n streetAddress1,\n streetAddress2,\n city,\n state,\n zip,\n country,\n phone,\n },\n email: user.email,\n orderName,\n orderId,\n shopOrderId,\n metadata,\n };\n\n // Prepare platform configuration like other functions do\n const platformConfig = {\n domain,\n accessToken,\n createPurchaseFunction: platform.createPurchaseFunction,\n ...metadata,\n };\n\n try {\n const orderPlacementRes = await createChannelPurchase({\n platform: platformConfig,\n cartItems,\n shipping: {\n firstName,\n lastName,\n address1: streetAddress1,\n address2: streetAddress2,\n city,\n province: state,\n zip,\n country,\n phone,\n email: user.email,\n currency,\n },\n notes: \"\",\n });\n\n if (orderPlacementRes.error) {\n await updateCartItems({\n cartItems,\n error: `ORDER_PLACEMENT_ERROR: ${orderPlacementRes.error}`,\n query,\n });\n }\n\n if (orderPlacementRes.purchaseId) {\n await updateCartItems({\n cartItems,\n url: orderPlacementRes.url,\n purchaseId: orderPlacementRes.purchaseId,\n query,\n });\n }\n } catch (error: any) {\n await updateCartItems({\n cartItems,\n error: `ORDER_PLACEMENT_ERROR: ${error.message || \"Error on order placement. Order may have been placed.\"}`,\n query,\n });\n }\n\n const cartCount = await query.CartItem.count({\n where: {\n order: {\n id: { equals: orderId },\n },\n url: { equals: \"\" },\n purchaseId: { equals: \"\" },\n },\n });\n\n if (cartCount === 0) {\n const updatedOrder = await query.Order.updateOne({\n where: { id: orderId },\n data: {\n status: \"AWAITING\",\n },\n query: `\n id\n orderId\n cartItems {\n id,\n name,\n quantity,\n price,\n image,\n productId,\n variantId,\n sku,\n purchaseId,\n lineItemId,\n channel {\n id\n name\n },\n url,\n error,\n }\n shop {\n platform {\n addCartToPlatformOrderFunction\n }\n }\n `,\n });\n\n try {\n await addCartToPlatformOrder({\n platform: updatedOrder.shop.platform,\n cartItems: updatedOrder.cartItems,\n orderId: updatedOrder.orderId,\n });\n } catch (error: any) {\n console.warn(\n \"Warning: Add cart to platform order function failed:\",\n error.message\n );\n }\n\n processed.push(updatedOrder);\n } else {\n const updatedOrder = await query.Order.updateOne({\n where: { id: orderId },\n data: {\n status: \"PENDING\",\n },\n query: `\n orderId\n cartItems {\n channel {\n id\n }\n image\n price\n id\n quantity\n productId\n variantId\n sku\n }\n `,\n });\n\n processed.push(updatedOrder);\n }\n }\n }\n return processed;\n}", "import type { KeystoneContext } from '@keystone-6/core/types';\nimport { executeChannelAdapterFunction } from '../../../integrations/channel/lib/executor';\n\ninterface AddMatchToCartArgs {\n orderId: string;\n}\n\nexport async function getMatches({ orderId, context }: { orderId: string; context: KeystoneContext }) {\n async function createCartItems({ matches }: { matches: any[] }) {\n if (matches.length > 0) {\n let result;\n for (const existingMatch of matches) {\n for (const {\n channel,\n productId,\n variantId,\n price: matchPrice,\n id,\n user,\n ...rest\n } of existingMatch.output) {\n // Create platform object with all necessary data\n const platformData = {\n ...channel.platform,\n domain: channel.domain,\n accessToken: channel.accessToken,\n };\n\n // Use the new executor pattern to get product data\n const productResult = await executeChannelAdapterFunction({\n platform: platformData,\n functionName: \"getProductFunction\",\n args: { productId, variantId },\n });\n \n const product = productResult.product;\n\n // Simple string comparison - no parsing needed\n const currentPriceStr = String(product.price || '');\n const savedPriceStr = String(matchPrice || '');\n const hasPriceChange = currentPriceStr !== savedPriceStr;\n \n // Store price as text (no parsing needed)\n const priceValue = currentPriceStr;\n\n result = await context.query.CartItem.createOne({\n data: {\n price: priceValue,\n productId,\n variantId,\n image: product.image,\n name: product.title,\n order: { connect: { id: order.id } },\n channel: { connect: { id: channel.id } },\n ...(hasPriceChange && {\n error: `PRICE_CHANGE: Price changed: ${savedPriceStr} \u2192 ${currentPriceStr}. Verify before placing order.`,\n }),\n user: { connect: { id: user.id } },\n ...rest,\n },\n });\n }\n }\n\n return result;\n }\n }\n\n const order = await context.query.Order.findOne({\n where: {\n id: orderId,\n },\n query: `\n id\n user {\n id\n } \n lineItems {\n image\n price\n id\n quantity\n productId\n variantId\n lineItemId\n }`,\n });\n\n if (!order) {\n throw new Error(\"Order not found\");\n }\n\n const allMatches = await context.query.Match.findMany({\n where: {\n user: {\n id: { equals: order.user.id },\n },\n AND: order.lineItems.map(({ productId, variantId, quantity }: any) => ({\n input: {\n some: {\n productId: { equals: productId },\n variantId: { equals: variantId },\n quantity: { equals: quantity },\n },\n },\n })),\n },\n query: ` \n inputCount\n outputCount\n input {\n id\n quantity\n productId\n variantId\n shop {\n id\n }\n user {\n id\n }\n }\n output {\n id\n quantity\n productId\n variantId\n price\n channel {\n id\n domain\n accessToken\n platform {\n id\n getProductFunction\n }\n }\n user {\n id\n }\n }\n `,\n });\n\n const [filt] = allMatches.filter(\n ({ inputCount }) => inputCount === order.lineItems.length\n );\n\n if (filt) {\n return await createCartItems({ matches: [filt] });\n } else {\n if (order.lineItems.length > 1) {\n const output = await Promise.all(\n order.lineItems.map(async ({ quantity, variantId, productId }: any) => {\n const singleAllMatches = await context.query.Match.findMany({\n where: {\n user: {\n id: { equals: order.user.id },\n },\n AND: [\n {\n input: {\n every: {\n productId: { equals: productId },\n variantId: { equals: variantId },\n quantity: { equals: quantity },\n },\n },\n },\n ],\n },\n query: `\n input {\n id\n quantity\n productId\n variantId\n shop {\n id\n }\n }\n output {\n id\n quantity\n productId\n variantId\n price\n channel {\n id\n domain\n accessToken\n platform {\n id\n getProductFunction\n }\n }\n user {\n id\n }\n }\n `,\n });\n\n const [singleFilt] = singleAllMatches;\n\n if (singleFilt) {\n return singleFilt;\n }\n await context.query.Order.updateOne({\n where: { id: orderId },\n data: {\n error: \"MATCH_ERROR: Some lineItems not matched\",\n status: \"PENDING\",\n },\n });\n })\n );\n\n if (output.filter((value) => value !== undefined).length) {\n return await createCartItems({ matches: output });\n }\n } else {\n await context.query.Order.updateOne({\n where: { id: orderId },\n data: {\n error: \"MATCH_ERROR: No matches found\",\n },\n });\n }\n }\n}\n\nasync function addMatchToCart(\n root: any,\n { orderId }: AddMatchToCartArgs,\n context: KeystoneContext\n) {\n const session = context.session;\n if (!session?.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n const cartItemsFromMatch = await getMatches({\n orderId,\n context,\n });\n\n if (cartItemsFromMatch) {\n return await context.db.Order.findOne({\n where: { id: orderId },\n });\n } else {\n throw new Error(\"No Matches found\");\n }\n}\n\nexport default addMatchToCart;", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport { relationship, text, timestamp } from \"@keystone-6/core/fields\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const TrackingDetail = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageOrders,\n },\n filter: {\n query: rules.canReadOrders,\n update: rules.canManageOrders,\n delete: rules.canManageOrders,\n },\n },\n hooks: {\n resolveInput: {\n create: ({ operation, resolvedData, context }) => {\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n return {\n ...resolvedData,\n user: { connect: { id: context.session.itemId } },\n };\n }\n return resolvedData;\n },\n },\n afterOperation: async ({ operation, item, context }) => {\n if (operation === \"create\") {\n const sudoContext = context.sudo();\n \n // Get tracking detail with related data\n const foundTracking = await sudoContext.query.TrackingDetail.findOne({\n where: { id: String(item.id) },\n query: `\n id\n trackingNumber\n trackingCompany\n purchaseId\n cartItems {\n id\n purchaseId\n order {\n id\n orderName\n orderId\n status\n shop {\n id\n domain\n accessToken\n platform {\n id\n name\n addTrackingFunction\n }\n }\n }\n }\n `,\n });\n \n if (!foundTracking?.cartItems?.length) {\n return;\n }\n \n const firstCartItem = foundTracking.cartItems[0];\n const order = firstCartItem.order;\n \n // Execute shop platform addTracking function\n if (order.shop?.platform?.addTrackingFunction) {\n try {\n // Use the executor pattern\n const { addShopTracking } = await import('../../integrations/shop/lib/executor');\n \n await addShopTracking({\n platform: {\n ...order.shop.platform,\n domain: order.shop.domain,\n accessToken: order.shop.accessToken,\n },\n order: order,\n trackingCompany: foundTracking.trackingCompany,\n trackingNumber: foundTracking.trackingNumber,\n });\n } catch (error) {\n console.error('Error calling addTracking:', error);\n // Don't throw - continue with order status update even if shop tracking fails\n }\n }\n \n // Check if all cart items for this order have tracking\n const foundOrder = await sudoContext.query.Order.findOne({\n where: { id: order.id },\n query: `\n id\n orderName\n status\n cartItems(\n where: {\n AND: [\n { trackingDetails: { none: {} } },\n { status: { not: { equals: \"CANCELLED\" } } }\n ]\n }\n ) {\n id\n status\n }\n `,\n });\n \n // If no untracked items remain, update order status to COMPLETE\n if (foundOrder && foundOrder.cartItems.length === 0 && foundOrder.status === \"AWAITING\") {\n await sudoContext.query.Order.updateOne({\n where: { id: foundOrder.id },\n data: {\n status: \"COMPLETE\",\n },\n });\n }\n }\n },\n },\n ui: {\n listView: {\n initialColumns: [\"trackingCompany\", \"trackingNumber\", \"purchaseId\"],\n },\n },\n fields: {\n // Tracking information\n trackingCompany: text({\n validation: { isRequired: true },\n }),\n trackingNumber: text({\n validation: { isRequired: true },\n }),\n purchaseId: text(),\n\n // Relationships\n cartItems: relationship({\n ref: \"CartItem.trackingDetails\",\n many: true,\n ui: {\n displayMode: \"cards\",\n cardFields: [\"name\", \"quantity\", \"status\"],\n },\n }),\n user: relationship({\n ref: \"User.trackingDetails\",\n }),\n\n ...trackingFields,\n },\n});\n", "import { list } from '@keystone-6/core'\nimport { allOperations } from '@keystone-6/core/access'\nimport { float, integer, relationship, text, timestamp } from '@keystone-6/core/fields'\n\nimport { isSignedIn, permissions, rules } from '../access'\nimport { trackingFields } from \"./trackingFields\";\n\nexport const LineItem = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageOrders,\n },\n filter: {\n query: rules.canReadOrders,\n update: rules.canManageOrders,\n delete: rules.canManageOrders,\n },\n },\n hooks: {\n resolveInput: {\n create: ({ operation, resolvedData, context }) => {\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n return {\n ...resolvedData,\n user: { connect: { id: context.session.itemId } },\n }\n }\n return resolvedData\n },\n },\n },\n ui: {\n listView: {\n initialColumns: ['name', 'quantity', 'price', 'order'],\n },\n },\n fields: {\n // Product information\n name: text({\n validation: { isRequired: true },\n }),\n image: text(),\n price: float(),\n quantity: integer(),\n \n // Product identifiers\n productId: text(),\n variantId: text(),\n sku: text(),\n lineItemId: text(),\n \n // Relationships\n order: relationship({\n ref: 'Order.lineItems',\n ui: {\n displayMode: 'cards',\n cardFields: ['orderId', 'orderName'],\n },\n }),\n user: relationship({\n ref: 'User.lineItems',\n }),\n \n ...trackingFields\n },\n})", "import { list } from '@keystone-6/core'\nimport { allOperations } from '@keystone-6/core/access'\nimport { float, integer, relationship, text, timestamp } from '@keystone-6/core/fields'\n\nimport { isSignedIn, permissions, rules } from '../access'\nimport { trackingFields } from './trackingFields'\n\nexport const CartItem = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageOrders,\n },\n filter: {\n query: rules.canReadOrders,\n update: rules.canManageOrders,\n delete: rules.canManageOrders,\n },\n },\n hooks: {\n resolveInput: {\n create: ({ operation, resolvedData, context }) => {\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n return {\n ...resolvedData,\n user: { connect: { id: context.session.itemId } },\n }\n }\n return resolvedData\n },\n },\n },\n ui: {\n listView: {\n initialColumns: ['name', 'quantity', 'price', 'status', 'channel'],\n },\n },\n fields: {\n // Product information\n name: text({\n validation: { isRequired: true },\n }),\n image: text(),\n price: text(),\n quantity: integer(),\n \n // Product identifiers\n productId: text(),\n variantId: text(),\n sku: text(),\n lineItemId: text(),\n \n // Processing information\n url: text(),\n error: text({\n ui: {\n displayMode: 'textarea',\n },\n }),\n purchaseId: text(),\n status: text({ defaultValue: 'PENDING' }),\n \n // Relationships\n order: relationship({\n ref: 'Order.cartItems',\n ui: {\n displayMode: 'cards',\n cardFields: ['orderId', 'orderName'],\n },\n }),\n channel: relationship({\n ref: 'Channel.cartItems',\n ui: {\n displayMode: 'cards',\n cardFields: ['name', 'domain'],\n },\n }),\n trackingDetails: relationship({\n ref: 'TrackingDetail.cartItems',\n many: true,\n }),\n user: relationship({\n ref: 'User.cartItems',\n }),\n \n ...trackingFields\n },\n})", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport { json, relationship, text, timestamp, virtual } from \"@keystone-6/core/fields\";\nimport { graphql } from \"@keystone-6/core\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { getBaseUrl } from '../../dashboard/lib/getBaseUrl';\nimport { executeChannelAdapterFunction } from '../utils/channelProviderAdapter';\n\nexport const Channel = list({\n access: {\n operation: {\n query: permissions.canSeeOtherChannels,\n create: permissions.canCreateChannels,\n update: permissions.canManageChannels,\n delete: permissions.canManageChannels,\n },\n filter: {\n query: rules.canReadChannels,\n update: rules.canManageChannels,\n delete: rules.canManageChannels,\n },\n },\n ui: {\n listView: {\n initialColumns: [\"name\", \"domain\", \"platform\"],\n },\n },\n fields: {\n name: text({\n validation: { isRequired: true },\n }),\n domain: text(),\n accessToken: text({\n ui: {\n displayMode: \"textarea\",\n },\n }),\n refreshToken: text({\n ui: {\n displayMode: \"textarea\",\n description: \"Long-lived OAuth refresh token (30 days)\",\n },\n }),\n tokenExpiresAt: timestamp({\n ui: {\n description: \"When the current access token expires\",\n },\n }),\n metadata: json({\n defaultValue: {},\n }),\n\n // Relationships\n platform: relationship({\n ref: \"ChannelPlatform.channels\",\n }),\n user: relationship({\n ref: \"User.channels\",\n hooks: {\n resolveInput: ({ operation, resolvedData, context }) => {\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n links: relationship({\n ref: \"Link.channel\",\n many: true,\n }),\n channelItems: relationship({\n ref: \"ChannelItem.channel\",\n many: true,\n }),\n cartItems: relationship({\n ref: \"CartItem.channel\",\n many: true,\n }),\n\n // Virtual field for webhooks with proper base URL\n webhooks: virtual({\n field: graphql.field({\n type: graphql.JSON,\n async resolve(item: any, args: any, context: any): Promise {\n try {\n const recommendedWebhooks = [\n {\n callbackUrl: `/api/handlers/channel/cancel-purchase/${item.id}`,\n topic: \"ORDER_CANCELLED\",\n description: \"When a purchase order is cancelled by this channel, enabling this will notify Openship to mark the cart item as cancelled and move the order to PENDING for reprocessing.\",\n },\n {\n callbackUrl: `/api/handlers/channel/create-tracking/${item.id}`,\n topic: \"TRACKING_CREATED\",\n description: \"When a purchase order is fulfilled by this channel, enabling this will notify Openship to add the tracking to the order and shop.\",\n },\n ];\n\n // Get platform data with relationships resolved\n const channelWithPlatform = await context.query.Channel.findOne({\n where: { id: String(item.id) },\n query: 'platform { getWebhooksFunction }'\n });\n\n if (!channelWithPlatform?.platform?.getWebhooksFunction) {\n return {\n success: false,\n error: \"Get webhooks function not configured\",\n recommendedWebhooks\n } as any;\n }\n\n const platformConfig: any = {\n domain: item.domain,\n accessToken: item.accessToken,\n getWebhooksFunction: channelWithPlatform.platform.getWebhooksFunction,\n ...(item.metadata || {}),\n };\n\n const webhooksResult = await executeChannelAdapterFunction({\n platform: platformConfig,\n functionName: 'getWebhooksFunction',\n args: {},\n });\n\n return {\n success: true,\n data: { webhooks: webhooksResult.webhooks || [] },\n recommendedWebhooks\n } as any;\n } catch (error) {\n console.error('Error in webhooks virtual field:', error);\n return {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n recommendedWebhooks: [\n {\n callbackUrl: `/api/handlers/channel/cancel-purchase/${item.id}`,\n topic: \"ORDER_CANCELLED\",\n description: \"When a purchase order is cancelled by this channel, enabling this will notify Openship to mark the cart item as cancelled and move the order to PENDING for reprocessing.\",\n },\n {\n callbackUrl: `/api/handlers/channel/create-tracking/${item.id}`,\n topic: \"TRACKING_CREATED\",\n description: \"When a purchase order is fulfilled by this channel, enabling this will notify Openship to add the tracking to the order and shop.\",\n },\n ]\n } as any;\n }\n },\n }),\n }),\n\n ...trackingFields,\n },\n});\n", "import {\n integer,\n text,\n relationship,\n virtual,\n float,\n} from \"@keystone-6/core/fields\";\nimport { graphql, list } from \"@keystone-6/core\";\nimport { isSignedIn, rules, permissions } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { getChannelProduct } from \"../extendGraphqlSchema/queries\";\n\nfunction mergeData(existingData: any, newData: any) {\n const updatedData = {};\n\n // Loop through all keys in existingData to create a base for updatedData\n Object.keys(existingData).forEach((key) => {\n // Default to existing data\n (updatedData as any)[key] = existingData[key];\n\n // Check if new data is provided for the key\n if (newData[key] !== undefined) {\n if (typeof newData[key] === \"object\" && newData[key] !== null) {\n // Handle connect and disconnect for relationships\n if (newData[key].connect) {\n (updatedData as any)[key] = newData[key].connect.id; // Use connected ID\n } else if (newData[key].disconnect) {\n (updatedData as any)[key] = null; // Disconnect the relationship\n }\n } else {\n // Directly assign new data if it's not an object or null\n (updatedData as any)[key] = newData[key];\n }\n }\n });\n\n return updatedData;\n}\n\nexport const ChannelItem = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: isSignedIn,\n },\n filter: {\n query: rules.canReadMatches,\n update: rules.canUpdateMatches,\n delete: rules.canUpdateMatches,\n },\n },\n fields: {\n quantity: integer(),\n productId: text(),\n variantId: text(),\n lineItemId: text(),\n price: text(),\n priceChanged: virtual({\n field: graphql.field({\n type: graphql.String,\n async resolve(item: any, args: any, context: any) {\n const channelItem = await context.query.ChannelItem.findOne({\n where: { id: item.id },\n query: 'price externalDetails { price }',\n });\n \n if (channelItem && channelItem.price && channelItem.externalDetails?.price) {\n const savedPrice = channelItem.price;\n const currentPrice = channelItem.externalDetails.price;\n \n if (savedPrice !== currentPrice) {\n return `Price changed from ${savedPrice} to ${currentPrice}`;\n }\n }\n return null;\n },\n }),\n }),\n externalDetails: virtual({\n field: graphql.field({\n type: graphql.object()({\n name: \"ChannelProduct\",\n fields: {\n image: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.image }),\n title: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.title }),\n productId: graphql.field({ type: graphql.ID, resolve: (parent: any) => parent.productId }),\n variantId: graphql.field({ type: graphql.ID, resolve: (parent: any) => parent.variantId }),\n price: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.price }),\n availableForSale: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.availableForSale }),\n productLink: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.productLink }),\n inventory: graphql.field({ type: graphql.Int, resolve: (parent: any) => parent.inventory }),\n inventoryTracked: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.inventoryTracked }),\n error: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.error }),\n },\n }),\n resolve: async (item: any, args: any, context: any): Promise => {\n const channelItem = await context.query.ChannelItem.findOne({\n where: { id: item.id },\n query: \"channel { id }\",\n });\n\n if (!channelItem?.channel) {\n console.error(\"Channel not associated or missing.\");\n return { error: \"Channel not associated or missing.\" };\n }\n\n const channelId = String(channelItem.channel.id);\n\n try {\n const product = await getChannelProduct(\n null,\n {\n channelId: channelId,\n productId: item.productId,\n variantId: item.variantId,\n },\n context\n );\n return product;\n } catch (error) {\n console.error(\"Failed to fetch external details:\", error);\n return { error: \"Failed to fetch external details.\" };\n }\n },\n }),\n ui: {\n query:\n \"{ image title productId variantId price availableForSale productLink inventory inventoryTracked error }\",\n },\n }),\n matches: relationship({ ref: \"Match.output\", many: true }),\n channel: relationship({ ref: \"Channel.channelItems\" }),\n user: relationship({\n ref: \"User.channelItems\",\n hooks: {\n resolveInput({ operation, resolvedData, context }) {\n // Default to the currently logged in user on create.\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session?.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n ...trackingFields,\n },\n db: {\n extendPrismaSchema: (schema) => {\n // add a (poor) example of a multi-column unique constraint\n return schema.replace(\n /(model [^}]+)}/g,\n \"$1@@unique([quantity, productId, variantId, channelId, userId])\\n}\"\n );\n },\n },\n});", "import { searchChannelProducts } from \"../../utils/channelProviderAdapter\";\n\nasync function getMatches({ inputArray, user, context }: {\n inputArray: any[];\n user: { id: string };\n context: any;\n}) {\n const allMatches = await context.query.Match.findMany({\n where: {\n user: { id: { equals: user.id } },\n AND: inputArray.map(({ productId, variantId, quantity }) => ({\n input: {\n some: {\n productId,\n variantId,\n quantity,\n },\n },\n })),\n },\n query: ` \n id\n inputCount\n outputCount\n input {\n id\n quantity\n productId\n variantId\n shop {\n id\n }\n user {\n id\n }\n }\n output {\n id\n quantity\n productId\n variantId\n price\n channel {\n id\n domain\n accessToken\n name\n platform {\n id\n searchProductsFunction\n }\n }\n user {\n id\n }\n }\n `,\n });\n\n const [filt] = allMatches.filter(\n ({ inputCount }: any) => inputCount === inputArray.length\n );\n\n if (filt) {\n return [filt];\n }\n throw new Error(\"No match found\");\n}\n\nasync function getMatch(root: any, { input }: { input: any[] }, context: any) {\n const sesh = context.session;\n if (!sesh.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n const existingMatches = await getMatches({\n inputArray: input,\n user: { id: sesh.itemId },\n context,\n });\n\n const cleanEM = existingMatches.filter((a) => a !== undefined);\n\n if (cleanEM.length > 0) {\n const output = [];\n for (const existingMatch of cleanEM) {\n for (const {\n channel,\n productId,\n variantId,\n quantity,\n price: matchPrice,\n id,\n userId,\n channelId,\n ...rest\n } of existingMatch.output) {\n const { searchProductsFunction } = channel.platform;\n\n const searchResult = await searchChannelProducts({\n platform: channel.platform,\n searchEntry: productId,\n after: undefined,\n });\n \n const products = searchResult.products;\n\n const [productInfo] = products;\n productInfo.name = productInfo.title;\n output.push({ ...productInfo, channelName: channel.name, quantity });\n }\n }\n return output;\n }\n}\n\nexport default getMatch;", "async function getMatches({ inputArray, user, context }: {\n inputArray: any[];\n user: { id: string };\n context: any;\n}) {\n const allMatches = await context.query.Match.findMany({\n where: {\n user: { id: { equals: user.id } },\n AND: inputArray.map(({ productId, variantId, quantity }) => ({\n input: {\n some: {\n productId,\n variantId,\n quantity,\n },\n },\n })),\n },\n query: ` \n id\n inputCount\n `,\n });\n\n const filteredValues = allMatches.filter(\n ({ inputCount }: any) => inputCount === inputArray.length\n );\n\n // if (filteredValues.length) {\n // return allMatches.length;\n // } else {\n // return 0;\n // }\n return filteredValues.length;\n}\n\nasync function getMatchCount(root: any, { input }: { input: any[] }, context: any) {\n // 1. Query the current user see if they are signed in\n const sesh = context.session;\n if (!sesh.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n const existingMatchesCount = await getMatches({\n inputArray: input,\n user: { id: sesh.itemId },\n context,\n });\n\n return existingMatchesCount;\n}\n\nexport default getMatchCount;", "import { getShopWebhooks as executeGetShopWebhooks } from \"../../utils/shopProviderAdapter\";\n\ninterface GetShopWebhooksArgs {\n shopId: string;\n}\n\nasync function getShopWebhooks(\n root: any,\n { shopId }: GetShopWebhooksArgs,\n context: any\n) {\n try {\n // Fetch the shop using the provided shopId\n const shop = await context.query.Shop.findOne({\n where: { id: shopId },\n query: \"id domain accessToken platform { id getWebhooksFunction }\",\n });\n\n \n if (!shop) {\n throw new Error(\"Shop not found\");\n }\n\n if (!shop.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n const result = await executeGetShopWebhooks({\n platform: {\n ...shop.platform,\n domain: shop.domain,\n accessToken: shop.accessToken,\n },\n });\n\n return result.webhooks;\n } catch (error: any) {\n throw new Error(`Error getting shop webhooks: ${error.message}`);\n }\n}\n\nexport default getShopWebhooks;", "async function redirectToInit(root: any, { ids }: any, context: any) {\n // 1. Query the current user see if they are signed in\n const userCount = await context.sudo().query.User.count({});\n\n if (userCount === 0) {\n return true;\n }\n return false;\n}\n\nexport default redirectToInit;", "import type { KeystoneContext } from '@keystone-6/core/types';\nimport { searchShopOrders as searchShopOrdersExecutor } from \"../../utils/shopProviderAdapter\";\n\ninterface SearchShopOrdersArgs {\n shopId: string;\n searchEntry?: string;\n take: number;\n skip?: number;\n after?: string;\n status?: string;\n financialStatus?: string;\n fulfillmentStatus?: string;\n dateFrom?: string;\n dateTo?: string;\n}\n\nasync function searchShopOrders(\n root: any,\n { shopId, searchEntry, take = 25, skip = 0, after, status, financialStatus, fulfillmentStatus, dateFrom, dateTo }: SearchShopOrdersArgs,\n context: KeystoneContext\n) {\n // Validate input parameters\n if (!shopId || typeof shopId !== 'string') {\n throw new Error(\"Valid shop ID is required\");\n }\n\n if (take > 250) {\n throw new Error(\"Cannot fetch more than 250 orders at once\");\n }\n\n if (take < 1) {\n throw new Error(\"Take must be at least 1\");\n }\n // Fetch the shop using the provided shopId\n const shop = await context.query.Shop.findOne({\n where: { id: shopId },\n query: `\n id \n domain \n accessToken \n metadata\n platform { \n id \n name\n searchOrdersFunction \n appKey\n appSecret\n }\n `,\n });\n\n \n if (!shop) {\n throw new Error(\"Shop not found\");\n }\n\n if (!shop.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n if (!shop.platform.searchOrdersFunction) {\n throw new Error(\"Search orders function not configured.\");\n }\n\n // Prepare platform configuration with enhanced filtering\n const platformConfig = {\n domain: shop.domain,\n accessToken: shop.accessToken,\n ...shop.metadata,\n };\n\n // Build advanced filter options\n const filterOptions = {\n searchEntry,\n after,\n take,\n skip,\n // Advanced filtering capabilities\n filters: {\n status: status || undefined,\n financialStatus: financialStatus || undefined,\n fulfillmentStatus: fulfillmentStatus || undefined,\n createdAtMin: dateFrom ? new Date(dateFrom).toISOString() : undefined,\n createdAtMax: dateTo ? new Date(dateTo).toISOString() : undefined,\n },\n };\n\n try {\n const result = await searchShopOrdersExecutor({\n platform: {\n ...shop.platform,\n ...platformConfig,\n },\n ...filterOptions,\n });\n\n // Enhance the result with additional metadata\n return {\n orders: result.orders || [],\n pageInfo: {\n hasNextPage: result.pageInfo?.hasNextPage || false,\n hasPreviousPage: result.pageInfo?.hasPreviousPage || false,\n startCursor: result.pageInfo?.startCursor || null,\n endCursor: result.pageInfo?.endCursor || null,\n },\n totalCount: result.totalCount || null,\n shopInfo: {\n id: shop.id,\n domain: shop.domain,\n platformName: shop.platform.name,\n },\n searchMetadata: {\n searchEntry,\n filtersApplied: Object.keys(filterOptions.filters).filter(\n key => (filterOptions.filters as Record)[key] !== undefined\n ),\n fetchedAt: new Date().toISOString(),\n resultCount: result.orders?.length || 0,\n },\n };\n } catch (error) {\n console.error(`Error searching orders for shop ${shop.id}:`, error);\n throw new Error(`Failed to search orders from ${shop.platform.name}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n\nexport default searchShopOrders;", "\"use server\";\n\nimport { searchShopProducts } from \"../../utils/shopProviderAdapter\";\n\nasync function searchShopProductsQuery(\n root: any,\n { shopId, searchEntry, after }: { shopId: string; searchEntry: string; after?: string },\n context: any\n) {\n const sudoContext = context.sudo();\n\n // Fetch the shop using the provided shopId\n const shop = await sudoContext.query.Shop.findOne({\n where: { id: shopId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n name\n searchProductsFunction\n appKey\n appSecret\n }\n `,\n });\n\n if (!shop) {\n throw new Error(\"Shop not found\");\n }\n\n if (!shop.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n if (!shop.platform.searchProductsFunction) {\n throw new Error(\"Search products function not configured.\");\n }\n\n // Prepare platform configuration\n const platformConfig = {\n domain: shop.domain,\n accessToken: shop.accessToken,\n ...shop.metadata,\n };\n\n try {\n const result = await searchShopProducts({\n platform: {\n ...shop.platform,\n ...platformConfig,\n },\n searchEntry: searchEntry || \"\",\n after,\n });\n\n return result.products;\n } catch (error) {\n console.error(\"Error searching shop products:\", error);\n throw new Error(`Failed to search products: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n\nexport default searchShopProductsQuery;", "'use server';\n\nimport { searchChannelProducts } from '../../utils/channelProviderAdapter';\n\nasync function searchChannelProductsQuery(\n root: any,\n {\n channelId,\n searchEntry,\n after,\n }: { channelId: string; searchEntry: string; after?: string },\n context: any,\n) {\n console.log(\"helllooooo\")\n const sudoContext = context.sudo();\n\n // Fetch the channel using the provided channelId\n const channel = await sudoContext.query.Channel.findOne({\n where: { id: channelId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n name\n searchProductsFunction\n }\n `,\n });\n\n if (!channel) {\n throw new Error('Channel not found');\n }\n\n if (!channel.platform) {\n throw new Error('Platform configuration not specified.');\n }\n\n if (!channel.platform.searchProductsFunction) {\n throw new Error('Search products function not configured.');\n }\n\n // Prepare platform configuration\n const platformConfig = {\n domain: channel.domain,\n accessToken: channel.accessToken,\n searchProductsFunction: channel.platform.searchProductsFunction,\n ...channel.metadata,\n };\n\n try {\n const result = await searchChannelProducts({\n platform: platformConfig,\n searchEntry: searchEntry || '',\n after,\n });\n\n return result.products;\n } catch (error: any) {\n console.error('Error searching channel products:', error);\n throw new Error(`Failed to search products: ${error.message}`);\n }\n}\n\nexport default searchChannelProductsQuery;", "import { getChannelWebhooks as executeGetChannelWebhooks } from \"../../utils/channelProviderAdapter\";\n\ninterface GetChannelWebhooksArgs {\n channelId: string;\n}\n\nasync function getChannelWebhooks(\n root: any,\n { channelId }: GetChannelWebhooksArgs,\n context: any\n) {\n try {\n // Fetch the channel using the provided channelId\n const channel = await context.query.Channel.findOne({\n where: { id: channelId },\n query: \"id domain accessToken platform { id getWebhooksFunction }\",\n });\n\n if (!channel) {\n throw new Error(\"Channel not found\");\n }\n\n if (!channel.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n const result = await executeGetChannelWebhooks({\n platform: channel.platform,\n });\n\n return result.webhooks;\n } catch (error: any) {\n throw new Error(`Error getting channel webhooks: ${error.message}`);\n }\n}\n\nexport default getChannelWebhooks;", "async function getFilteredMatches(root: any, args: any, context: any) {\n // Fetch all matches\n const matches = await context.query.Match.findMany({\n query: `\n id \n outputPriceChanged\n inventoryNeedsToBeSynced { syncEligible sourceQuantity targetQuantity }\n input { \n id quantity productId variantId lineItemId \n externalDetails { title image price productLink inventory inventoryTracked } \n shop { id name } \n } \n output { \n id quantity productId variantId lineItemId \n externalDetails { title image price productLink inventory inventoryTracked } \n price channel { id name } \n }\n `,\n });\n\n // console.log(matches);\n // Filter matches based on inventoryNeedsToBeSynced.syncEligible\n const filteredMatches = matches.filter((match: any) => match.inventoryNeedsToBeSynced.syncEligible);\n\n // Return the filtered matches\n return filteredMatches;\n}\n\nexport default getFilteredMatches;", "import { getChannelProduct as executeGetChannelProduct } from \"../../utils/channelProviderAdapter\";\n\nasync function getChannelProduct(\n root: any,\n { channelId, productId, variantId }: {\n channelId: string;\n productId?: string;\n variantId?: string;\n },\n context: any\n) {\n // Fetch the channel using the provided channelId\n const channel = await context.query.Channel.findOne({\n where: { id: channelId },\n query: \"id domain accessToken platform { id getProductFunction }\",\n });\n\n if (!channel) {\n throw new Error(\"Channel not found\");\n }\n\n if (!channel.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n // Prepare platform configuration\n const platformConfig = {\n domain: channel.domain,\n accessToken: channel.accessToken,\n getProductFunction: channel.platform.getProductFunction,\n ...channel.metadata,\n };\n\n try {\n const result = await executeGetChannelProduct({\n platform: platformConfig,\n productId: productId!,\n variantId: variantId,\n });\n\n return result.product;\n } catch (error: any) {\n throw new Error(`Failed to get channel product: ${error.message}`);\n }\n}\n\nexport default getChannelProduct;", "\"use server\";\n\nimport { getShopProduct } from \"../../utils/shopProviderAdapter\";\n\nasync function getShopProductQuery(\n root: any,\n { shopId, productId, variantId }: { shopId: string; productId: string; variantId?: string },\n context: any\n) {\n // Validate input parameters\n if (!shopId || typeof shopId !== 'string') {\n throw new Error(\"Valid shop ID is required\");\n }\n\n if (!productId || typeof productId !== 'string') {\n throw new Error(\"Valid product ID is required\");\n }\n\n const sudoContext = context.sudo();\n\n // Fetch the shop using the provided shopId\n const shop = await sudoContext.query.Shop.findOne({\n where: { id: shopId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n name\n getProductFunction\n }\n `,\n });\n\n if (!shop) {\n throw new Error(\"Shop not found\");\n }\n\n if (!shop.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n if (!shop.platform.getProductFunction) {\n throw new Error(\"Get product function not configured.\");\n }\n\n // Prepare platform configuration\n const platformConfig = {\n domain: shop.domain,\n accessToken: shop.accessToken,\n getProductFunction: shop.platform.getProductFunction,\n ...shop.metadata,\n };\n\n try {\n const result = await getShopProduct({\n platform: platformConfig,\n productId: productId,\n variantId: variantId,\n });\n\n // Extract product data from result\n const productData = result.product || result;\n\n // Enhance the result with inventory information and platform data\n return {\n ...productData,\n shopId: shop.id,\n shopDomain: shop.domain,\n platformName: shop.platform.name,\n fetchedAt: new Date().toISOString(),\n // Include live inventory levels if available\n inventoryLevel: productData.inventory || null,\n inventoryTracked: productData.inventoryTracked || false,\n // Include pricing information\n price: productData.price || null,\n compareAtPrice: productData.compareAtPrice || null,\n // Include availability\n availableForSale: productData.availableForSale || false,\n };\n } catch (error) {\n console.error(\"Error getting shop product:\", error);\n throw new Error(`Failed to get product from ${shop.platform.name}: ${error instanceof Error ? error.message : 'Unknown error'}`);\n }\n}\n\nexport default getShopProductQuery;", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport {\n json,\n relationship,\n select,\n text,\n timestamp,\n virtual,\n} from \"@keystone-6/core/fields\";\nimport { graphql } from \"@keystone-6/core\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { getBaseUrl } from '../../dashboard/lib/getBaseUrl';\nimport { executeShopAdapterFunction } from '../utils/shopProviderAdapter';\n\nexport const Shop = list({\n access: {\n operation: {\n query: permissions.canSeeOtherShops,\n create: permissions.canCreateShops,\n update: permissions.canManageShops,\n delete: permissions.canManageShops,\n },\n filter: {\n query: rules.canReadShops,\n update: rules.canManageShops,\n delete: rules.canManageShops,\n },\n },\n ui: {\n listView: {\n initialColumns: [\"name\", \"domain\", \"platform\", \"linkMode\"],\n },\n },\n fields: {\n name: text({\n validation: { isRequired: true },\n }),\n domain: text(),\n accessToken: text({\n ui: {\n displayMode: \"textarea\",\n },\n }),\n refreshToken: text({\n ui: {\n displayMode: \"textarea\",\n description: \"Long-lived OAuth refresh token (30 days)\",\n },\n }),\n tokenExpiresAt: timestamp({\n ui: {\n description: \"When the current access token expires\",\n },\n }),\n linkMode: select({\n options: [\n { label: \"Sequential\", value: \"sequential\" },\n { label: \"Simultaneous\", value: \"simultaneous\" },\n ],\n defaultValue: \"sequential\",\n }),\n metadata: json({\n defaultValue: {},\n }),\n\n // Relationships\n platform: relationship({\n ref: \"ShopPlatform.shops\",\n }),\n user: relationship({\n ref: \"User.shops\",\n hooks: {\n resolveInput: ({ operation, resolvedData, context }) => {\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n links: relationship({\n ref: \"Link.shop\",\n many: true,\n }),\n orders: relationship({\n ref: \"Order.shop\",\n many: true,\n }),\n shopItems: relationship({\n ref: \"ShopItem.shop\",\n many: true,\n }),\n\n // Virtual field for webhooks with proper base URL\n webhooks: virtual({\n field: graphql.field({\n type: graphql.JSON,\n async resolve(item: any, args: any, context: any): Promise {\n try {\n const recommendedWebhooks = [\n {\n callbackUrl: `/api/handlers/shop/create-order/${item.id}`,\n topic: \"ORDER_CREATED\",\n description: \"When an order is created on this shop, Openship will create the order to be fulfilled.\",\n },\n {\n callbackUrl: `/api/handlers/shop/cancel-order/${item.id}`,\n topic: \"ORDER_CANCELLED\",\n description: \"When an order is cancelled on this shop, Openship will mark the order status cancelled\",\n },\n {\n callbackUrl: `/api/handlers/shop/cancel-order/${item.id}`,\n topic: \"ORDER_CHARGEBACKED\",\n description: \"When an order is chargebacked on this shop, Openship will mark the order status cancelled\",\n },\n ];\n\n // Get platform data with relationships resolved\n const shopWithPlatform = await context.query.Shop.findOne({\n where: { id: item.id },\n query: 'platform { getWebhooksFunction }'\n });\n\n if (!shopWithPlatform?.platform?.getWebhooksFunction) {\n return {\n success: false,\n error: \"Get webhooks function not configured\",\n recommendedWebhooks\n } as any;\n }\n\n const platformConfig = {\n domain: item.domain,\n accessToken: item.accessToken,\n getWebhooksFunction: shopWithPlatform.platform.getWebhooksFunction,\n ...(item.metadata || {}),\n };\n\n const webhooksResult = await executeShopAdapterFunction({\n platform: platformConfig,\n functionName: 'getWebhooksFunction',\n args: {},\n });\n\n return {\n success: true,\n data: { webhooks: webhooksResult.webhooks || [] },\n recommendedWebhooks\n } as any;\n } catch (error) {\n console.error('Error in webhooks virtual field:', error);\n return {\n success: false,\n error: (error as any)?.message || 'Unknown error',\n recommendedWebhooks: [\n {\n callbackUrl: `/api/handlers/shop/create-order/${item.id}`,\n topic: \"ORDER_CREATED\",\n description: \"When an order is created on this shop, Openship will create the order to be fulfilled.\",\n },\n {\n callbackUrl: `/api/handlers/shop/cancel-order/${item.id}`,\n topic: \"ORDER_CANCELLED\",\n description: \"When an order is cancelled on this shop, Openship will mark the order status cancelled\",\n },\n {\n callbackUrl: `/api/handlers/shop/cancel-order/${item.id}`,\n topic: \"ORDER_CHARGEBACKED\",\n description: \"When an order is chargebacked on this shop, Openship will mark the order status cancelled\",\n },\n ]\n } as any;\n }\n },\n }),\n }),\n\n ...trackingFields,\n },\n});\n", "import {\n integer,\n text,\n relationship,\n virtual,\n float,\n} from \"@keystone-6/core/fields\";\nimport { graphql, list } from \"@keystone-6/core\";\nimport { isSignedIn, rules, permissions } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\nimport { getShopProduct } from \"../extendGraphqlSchema/queries\";\n\nexport const ShopItem = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: isSignedIn,\n },\n filter: {\n query: rules.canReadMatches,\n update: rules.canUpdateMatches,\n delete: rules.canUpdateMatches,\n },\n },\n fields: {\n quantity: integer(),\n productId: text(),\n variantId: text(),\n lineItemId: text(),\n externalDetails: virtual({\n field: graphql.field({\n type: graphql.object()({\n name: \"ShopProduct\",\n fields: {\n image: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.image }),\n title: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.title }),\n productId: graphql.field({ type: graphql.ID, resolve: (parent: any) => parent.productId }),\n variantId: graphql.field({ type: graphql.ID, resolve: (parent: any) => parent.variantId }),\n price: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.price }),\n availableForSale: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.availableForSale }),\n productLink: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.productLink }),\n inventory: graphql.field({ type: graphql.Int, resolve: (parent: any) => parent.inventory }),\n inventoryTracked: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.inventoryTracked }),\n error: graphql.field({ type: graphql.String, resolve: (parent: any) => parent.error }),\n },\n }),\n resolve: async (item: any, args: any, context: any): Promise => {\n const shopItem = await context.query.ShopItem.findOne({\n where: { id: item.id },\n query: \"shop { id }\",\n });\n\n if (!shopItem?.shop) {\n console.error(\"Shop not associated or missing.\");\n return { error: \"Shop not associated or missing.\" };\n }\n\n const shopId = shopItem.shop.id;\n\n try {\n const product = await getShopProduct(\n null,\n {\n shopId: shopId,\n productId: item.productId,\n variantId: item.variantId,\n },\n context\n );\n return product;\n } catch (error) {\n console.error(\"Failed to fetch external details:\", error);\n return { error: \"Failed to fetch external details.\" };\n }\n },\n }),\n ui: {\n query:\n \"{ image title productId variantId price availableForSale productLink inventory inventoryTracked error }\", // Adjust UI query as needed\n },\n }),\n matches: relationship({ ref: \"Match.input\", many: true }),\n shop: relationship({ ref: \"Shop.shopItems\" }),\n user: relationship({\n ref: \"User.shopItems\",\n hooks: {\n resolveInput({ operation, resolvedData, context }) {\n // Default to the currently logged in user on create.\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session?.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n ...trackingFields,\n },\n db: {\n extendPrismaSchema: (schema) => {\n // add a (poor) example of a multi-column unique constraint\n return schema.replace(\n /(model [^}]+)}/g,\n \"$1@@unique([quantity, productId, variantId, shopId, userId])\\n}\"\n );\n },\n },\n});", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport { relationship, timestamp, virtual } from \"@keystone-6/core/fields\";\nimport { graphql } from \"@keystone-6/core\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const Match = list({\n access: {\n operation: {\n create: permissions.canCreateMatches,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageMatches,\n },\n filter: {\n query: rules.canReadMatches,\n update: rules.canManageMatches,\n delete: rules.canManageMatches,\n },\n },\n hooks: {\n resolveInput: async ({ item, resolvedData, operation, context }) => {\n const { input, output } = resolvedData;\n\n const ensureShopItems = async (items: any) => {\n const processedItems = [];\n if (items.create) {\n for (const item of items.create) {\n let [existingItem] = await context.query.ShopItem.findMany({\n where: {\n productId: { equals: item.productId },\n variantId: { equals: item.variantId },\n quantity: { equals: item.quantity },\n shop: { id: { equals: item.shop.connect.id } },\n user: {\n id: {\n equals: item.user?.connect?.id || context.session?.itemId,\n },\n },\n },\n query: \"id\",\n });\n\n if (!existingItem) {\n existingItem = await context.query.ShopItem.createOne({\n data: item,\n query: \"id\",\n });\n }\n\n processedItems.push({ id: existingItem.id });\n }\n }\n return processedItems;\n };\n\n const ensureChannelItems = async (items: any) => {\n const processedItems = [];\n if (items.create) {\n for (const item of items.create) {\n let existingItem = await context.query.ChannelItem.findOne({\n where: {\n productId: { equals: item.productId },\n variantId: { equals: item.variantId },\n quantity: { equals: item.quantity },\n channel: { id: { equals: item.channel.connect.id } },\n user: {\n id: {\n equals: item.user?.connect?.id || context.session?.itemId,\n },\n },\n },\n query: \"id\",\n });\n\n if (!existingItem) {\n existingItem = await context.query.ChannelItem.createOne({\n data: item,\n query: \"id\",\n });\n }\n\n processedItems.push({ id: existingItem.id });\n }\n }\n return processedItems;\n };\n\n if (input && input.create) {\n const processedInput = await ensureShopItems(input);\n resolvedData.input.connect = [\n ...(resolvedData.input.connect || []),\n ...processedInput,\n ];\n delete resolvedData.input.create;\n }\n\n if (output && output.create) {\n const processedOutput = await ensureChannelItems(output);\n resolvedData.output.connect = [\n ...(resolvedData.output.connect || []),\n ...processedOutput,\n ];\n delete resolvedData.output.create;\n }\n\n // Check for duplicate matches\n const checkForDuplicate = async (inputIds: any) => {\n const existingMatches = await context.query.Match.findMany({\n where: {\n input: {\n some: { id: { in: inputIds } },\n },\n },\n query: \"id input { id }\",\n });\n\n return existingMatches.some((match) => {\n const matchInputIds = match.input.map((item: any) => item.id);\n return (\n matchInputIds.length === inputIds.length &&\n matchInputIds.every((id: any) => inputIds.includes(id))\n );\n });\n };\n\n if (operation === \"create\") {\n if (\n resolvedData.input.connect &&\n resolvedData.input.connect.length > 0\n ) {\n const inputIds = resolvedData.input.connect.map((item: any) => item.id);\n const isDuplicate = await checkForDuplicate(inputIds);\n\n if (isDuplicate) {\n throw new Error(\n \"A match with the same input combination already exists.\"\n );\n }\n }\n }\n\n if (operation === \"update\") {\n if (resolvedData.input) {\n // Fetch the current state of the match being updated\n const matchToUpdate = await context.query.Match.findOne({\n where: { id: String(item.id) },\n query: `id input { id productId variantId quantity shop { id } }`,\n });\n\n const newInputs = resolvedData.input.connect\n ? await Promise.all(\n resolvedData.input.connect.map(async (connectItem: any) => {\n return await context.query.ShopItem.findOne({\n where: { id: connectItem.id },\n query: `id productId variantId quantity shop { id }`,\n });\n })\n )\n : [];\n\n const disconnectedIds = resolvedData.input.disconnect\n ? resolvedData.input.disconnect.map((item: any) => item.id)\n : [];\n\n const remainingCurrentInputs = matchToUpdate.input.filter(\n (input: any) => !disconnectedIds.includes(input.id)\n );\n\n const combinedInputs = [...remainingCurrentInputs, ...newInputs];\n const inputIds = combinedInputs.map((item) => item.id);\n\n const isDuplicate = await checkForDuplicate(inputIds);\n\n if (isDuplicate) {\n throw new Error(\n \"A match with the same input combination already exists.\"\n );\n }\n }\n }\n\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n resolvedData.user = { connect: { id: context.session.itemId } };\n }\n\n return resolvedData;\n },\n },\n ui: {\n listView: {\n initialColumns: [\"input\", \"output\", \"user\"],\n },\n },\n fields: {\n // Virtual fields for match status\n outputPriceChanged: virtual({\n field: graphql.field({\n type: graphql.String,\n resolve() {\n return \"Price change detection for output items\";\n },\n }),\n ui: {\n itemView: { fieldMode: \"read\" },\n listView: { fieldMode: \"hidden\" },\n },\n }),\n inventoryNeedsToBeSynced: virtual({\n field: graphql.field({\n type: graphql.object()({\n name: \"MatchInventoryData\",\n fields: {\n syncEligible: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.syncEligible }),\n sourceQuantity: graphql.field({ type: graphql.Int, resolve: (parent: any) => parent.sourceQuantity }),\n targetQuantity: graphql.field({ type: graphql.Int, resolve: (parent: any) => parent.targetQuantity }),\n syncNeeded: graphql.field({ type: graphql.Boolean, resolve: (parent: any) => parent.syncNeeded }),\n },\n }),\n async resolve(item, args, context) {\n const match = await context.query.Match.findOne({\n where: { id: String(item.id) },\n query: `\n input { quantity externalDetails { inventory } }\n output { quantity externalDetails { inventory } }\n `,\n });\n\n const result = {\n syncEligible: false,\n sourceQuantity: null,\n targetQuantity: null,\n syncNeeded: false,\n };\n\n if (match?.input?.length === 1 && match?.output?.length === 1) {\n const input = match.input[0];\n const output = match.output[0];\n\n if (\n input.quantity === 1 &&\n output.quantity === 1 &&\n input.externalDetails?.inventory !== undefined &&\n output.externalDetails?.inventory !== undefined\n ) {\n result.syncEligible = true;\n result.sourceQuantity = input.externalDetails.inventory;\n result.targetQuantity = output.externalDetails.inventory;\n }\n }\n\n result.syncNeeded = result.syncEligible && \n result.sourceQuantity !== result.targetQuantity;\n\n return result;\n },\n }),\n ui: {\n query: \"{ syncEligible sourceQuantity targetQuantity syncNeeded }\",\n itemView: { fieldMode: \"read\" },\n listView: { fieldMode: \"hidden\" },\n },\n }),\n\n // Relationships - Many-to-many between ShopItems and ChannelItems\n input: relationship({\n ref: \"ShopItem.matches\",\n many: true,\n ui: {\n displayMode: \"cards\",\n cardFields: [\"productId\", \"variantId\", \"quantity\"],\n inlineConnect: true,\n },\n }),\n output: relationship({\n ref: \"ChannelItem.matches\",\n many: true,\n ui: {\n displayMode: \"cards\",\n cardFields: [\"productId\", \"variantId\", \"quantity\", \"price\"],\n inlineConnect: true,\n },\n }),\n user: relationship({\n ref: \"User.matches\",\n }),\n\n ...trackingFields,\n },\n});\n", "import { list } from \"@keystone-6/core\";\nimport { allOperations } from \"@keystone-6/core/access\";\nimport {\n integer,\n json,\n relationship,\n timestamp,\n virtual,\n} from \"@keystone-6/core/fields\";\nimport { graphql } from \"@keystone-6/core\";\n\nimport { isSignedIn, permissions, rules } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const Link = list({\n access: {\n operation: {\n create: permissions.canCreateLinks,\n query: isSignedIn,\n update: isSignedIn,\n delete: permissions.canManageLinks,\n },\n filter: {\n query: rules.canReadLinks,\n update: rules.canManageLinks,\n delete: rules.canManageLinks,\n },\n },\n hooks: {\n resolveInput: {\n create: ({ operation, resolvedData, context }) => {\n // Auto-assign user if not provided\n if (!resolvedData.user && context.session?.itemId) {\n return {\n ...resolvedData,\n user: { connect: { id: context.session.itemId } },\n };\n }\n return resolvedData;\n },\n },\n beforeOperation: async ({ operation, resolvedData, context }) => {\n if (operation === \"create\") {\n const shopId = resolvedData.shop.connect.id;\n\n const existingLinks = await context.query.Link.findMany({\n where: { shop: { id: { equals: shopId } } },\n });\n\n // Calculate the next rank value\n const nextRank =\n existingLinks.length > 0 ? existingLinks.length + 1 : 1;\n\n resolvedData.rank = nextRank;\n }\n },\n },\n ui: {\n listView: {\n initialColumns: [\"shop\", \"channel\", \"rank\"],\n },\n },\n fields: {\n // Processing order\n rank: integer({\n defaultValue: 1,\n ui: {\n description: \"Processing order - lower numbers processed first\",\n },\n }),\n\n // Filter configuration\n filters: json({\n defaultValue: [],\n ui: {\n description: \"Order filtering rules\",\n },\n }),\n customWhere: json({\n defaultValue: {},\n ui: {\n description: \"Custom where clause for order filtering\",\n },\n }),\n\n // Virtual field for dynamic where clause\n dynamicWhereClause: virtual({\n field: graphql.field({\n type: graphql.String,\n resolve() {\n return \"Generated where clause based on filters\";\n },\n }),\n ui: {\n itemView: { fieldMode: \"read\" },\n listView: { fieldMode: \"hidden\" },\n },\n }),\n\n // Relationships\n shop: relationship({\n ref: \"Shop.links\",\n ui: {\n displayMode: \"cards\",\n cardFields: [\"name\", \"domain\"],\n },\n }),\n channel: relationship({\n ref: \"Channel.links\",\n ui: {\n displayMode: \"cards\",\n cardFields: [\"name\", \"domain\"],\n },\n }),\n user: relationship({\n ref: \"User.links\",\n }),\n\n ...trackingFields,\n },\n});\n", "import { list, group, graphql } from \"@keystone-6/core\";\nimport { relationship, text, virtual, json } from \"@keystone-6/core/fields\";\nimport { isSignedIn, rules, permissions } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const ShopPlatform = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: isSignedIn,\n },\n filter: {\n query: rules.canReadShops,\n update: rules.canManageShops,\n delete: rules.canManageShops,\n },\n },\n fields: {\n name: text({ validation: { isRequired: true } }),\n ...group({\n label: \"App Credentials\",\n description:\n \"Adding these fields will enable this platform to be installed as an app by users\",\n fields: {\n appKey: text(),\n appSecret: text(),\n callbackUrl: virtual({\n field: graphql.field({\n type: graphql.String,\n resolve: async (item: any, args: any, context: any) => {\n // Get the base URL from the request context\n let baseUrl = '';\n \n // Try to get from request headers if available\n if (context?.req?.headers) {\n const headers = context.req.headers;\n const host = headers['x-forwarded-host'] || headers['host'];\n const protocol = headers['x-forwarded-proto'] || 'https';\n \n if (host) {\n baseUrl = `${protocol}://${host}`;\n }\n }\n \n // Fallback to environment variable or default\n if (!baseUrl) {\n baseUrl = process.env.NEXT_PUBLIC_URL || 'http://localhost:3000';\n }\n \n // Return simplified callback URL (no platform ID needed)\n return `${baseUrl}/api/oauth/callback`;\n },\n }),\n ui: {\n description:\n \"Add this URL as the redirect URI in your OAuth app settings (same for all platforms)\",\n },\n }),\n },\n }),\n ...group({\n label: \"Adapter Functions\",\n description: \"These functions link to built-in adapters, but can also be external endpoints\",\n fields: {\n searchProductsFunction: text({ validation: { isRequired: true } }),\n getProductFunction: text({ validation: { isRequired: true } }),\n searchOrdersFunction: text({ validation: { isRequired: true } }),\n updateProductFunction: text({ validation: { isRequired: true } }),\n createWebhookFunction: text({ validation: { isRequired: true } }),\n oAuthFunction: text({\n validation: { isRequired: true },\n ui: {\n description: \"Function to initiate OAuth flow for this platform\",\n },\n }),\n oAuthCallbackFunction: text({\n validation: { isRequired: true },\n ui: {\n description: \"Function to handle OAuth callback for this platform\",\n },\n }),\n createOrderWebhookHandler: text({ validation: { isRequired: true } }),\n cancelOrderWebhookHandler: text({ validation: { isRequired: true } }),\n addTrackingFunction: text({ validation: { isRequired: true } }),\n orderLinkFunction: text({\n validation: { isRequired: true },\n ui: {\n description: \"Function to generate the order link for this platform\",\n },\n }),\n addCartToPlatformOrderFunction: text({ validation: { isRequired: true } }),\n getWebhooksFunction: text({ validation: { isRequired: true } }),\n deleteWebhookFunction: text({ validation: { isRequired: true } }),\n },\n }),\n shops: relationship({ ref: \"Shop.platform\", many: true }),\n user: relationship({\n ref: \"User.shopPlatforms\",\n hooks: {\n resolveInput({ operation, resolvedData, context }) {\n // Default to the currently logged in user on create.\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session?.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n ...trackingFields,\n },\n});", "import { graphql, group, list } from \"@keystone-6/core\";\nimport { relationship, text, virtual } from \"@keystone-6/core/fields\";\nimport { isSignedIn, rules, permissions } from \"../access\";\nimport { trackingFields } from \"./trackingFields\";\n\nexport const ChannelPlatform = list({\n access: {\n operation: {\n create: isSignedIn,\n query: isSignedIn,\n update: isSignedIn,\n delete: isSignedIn,\n },\n filter: {\n query: rules.canReadChannels,\n update: rules.canUpdateChannels,\n delete: rules.canUpdateChannels,\n },\n },\n fields: {\n name: text({ validation: { isRequired: true } }),\n ...group({\n label: \"App Credentials\",\n description:\n \"Adding these fields will enable this platform to be installed as an app by users.\",\n fields: {\n appKey: text(),\n appSecret: text(),\n callbackUrl: virtual({\n field: graphql.field({\n type: graphql.String,\n resolve: async (item: any, args: any, context: any) => {\n // Get the base URL from the request context\n let baseUrl = '';\n \n // Try to get from request headers if available\n if (context?.req?.headers) {\n const headers = context.req.headers;\n const host = headers['x-forwarded-host'] || headers['host'];\n const protocol = headers['x-forwarded-proto'] || 'https';\n \n if (host) {\n baseUrl = `${protocol}://${host}`;\n }\n }\n \n // Fallback to environment variable or default\n if (!baseUrl) {\n baseUrl = process.env.NEXT_PUBLIC_URL || 'http://localhost:3000';\n }\n \n // Return simplified callback URL (no platform ID needed)\n return `${baseUrl}/api/oauth/callback`;\n },\n }),\n ui: {\n description:\n \"Add this URL as the redirect URI in your OAuth app settings (same for all platforms)\",\n },\n }),\n },\n }),\n ...group({\n label: \"Adapter Functions\",\n description:\n \"These functions link to built-in adapters, but can also be external endpoints\",\n fields: {\n searchProductsFunction: text({ validation: { isRequired: true } }),\n getProductFunction: text({ validation: { isRequired: true } }),\n createPurchaseFunction: text({ validation: { isRequired: true } }),\n createWebhookFunction: text({ validation: { isRequired: true } }),\n oAuthFunction: text({\n validation: { isRequired: true },\n ui: {\n description: \"Function to initiate OAuth flow for this platform\",\n },\n }),\n oAuthCallbackFunction: text({\n validation: { isRequired: true },\n ui: {\n description: \"Function to handle OAuth callback for this platform\",\n },\n }),\n createTrackingWebhookHandler: text({ validation: { isRequired: true } }),\n cancelPurchaseWebhookHandler: text({ validation: { isRequired: true } }),\n getWebhooksFunction: text({ validation: { isRequired: true } }),\n deleteWebhookFunction: text({ validation: { isRequired: true } }),\n },\n }),\n channels: relationship({ ref: \"Channel.platform\", many: true }),\n user: relationship({\n ref: \"User.channelPlatforms\",\n hooks: {\n resolveInput({ operation, resolvedData, context }) {\n // Default to the currently logged in user on create.\n if (\n operation === \"create\" &&\n !resolvedData.user &&\n context.session?.itemId\n ) {\n return { connect: { id: context.session?.itemId } };\n }\n return resolvedData.user;\n },\n },\n }),\n ...trackingFields,\n },\n});", "import { User } from \"./User\";\nimport { ApiKey } from \"./ApiKey\";\nimport { Role } from \"./Role\";\nimport { Order } from \"./Order\";\nimport { TrackingDetail } from \"./TrackingDetail\";\nimport { LineItem } from \"./LineItem\";\nimport { CartItem } from \"./CartItem\";\nimport { Channel } from \"./Channel\";\nimport { ChannelItem } from \"./ChannelItem\";\nimport { Shop } from \"./Shop\";\nimport { ShopItem } from \"./ShopItem\";\nimport { Match } from \"./Match\";\nimport { Link } from \"./Link\";\nimport { ShopPlatform } from \"./ShopPlatform\";\nimport { ChannelPlatform } from \"./ChannelPlatform\";\n// Add other imports here if needed\n\n// Export individual models for direct import\nexport {\n User,\n Role,\n ApiKey,\n ShopPlatform,\n ChannelPlatform,\n Shop,\n Channel,\n Order,\n LineItem,\n CartItem,\n ShopItem,\n ChannelItem,\n Match,\n Link,\n TrackingDetail\n};\n\n// Also export as models object for compatibility\nexport const models = {\n User,\n Role,\n ApiKey,\n\n // E-commerce Platform Models\n ShopPlatform,\n ChannelPlatform,\n Shop,\n Channel,\n\n // Order Management Models\n Order,\n LineItem,\n CartItem,\n\n // Product & Inventory Models\n ShopItem,\n ChannelItem,\n Match,\n\n // Linking & Tracking Models\n Link,\n TrackingDetail,\n // Add other models here as needed\n};\n", "import { mergeSchemas } from \"@graphql-tools/schema\";\nimport {\n getMatch,\n getMatchCount,\n getShopWebhooks,\n redirectToInit,\n searchShopOrders,\n searchShopProducts,\n searchChannelProducts,\n getChannelWebhooks,\n getFilteredMatches,\n getChannelProduct,\n getShopProduct,\n} from \"./queries\";\nimport {\n addMatchToCart,\n addToCart,\n cancelOrder,\n cancelPurchase,\n matchOrder,\n overwriteMatch,\n placeOrders,\n createShopWebhook,\n deleteShopWebhook,\n updateShopProduct,\n createChannelWebhook,\n deleteChannelWebhook,\n createChannelPurchase,\n upsertMatch,\n} from \"./mutations\";\n\nconst graphql = String.raw;\n// Use graphql.tag or similar if needed to define GraphQL strings\nconst typeDefs = graphql`\n extend type Mutation {\n addToCart(\n channelId: ID\n image: String\n name: String\n price: String\n productId: String\n variantId: String\n quantity: String\n orderId: ID\n ): Order\n placeOrders(ids: [ID!]!): [Order]\n addMatchToCart(orderId: ID!): Order\n matchOrder(orderId: ID!): Match\n overwriteMatch(\n input: [ShopItemWhereInput!]\n output: [ChannelItemWhereInput!]\n ): Match\n cancelPurchase(purchaseId: String!): String\n cancelOrder(orderId: String!): String\n createShopWebhook(\n shopId: ID!\n topic: String!\n endpoint: String!\n ): CreateWebhookResponse\n deleteShopWebhook(shopId: ID!, webhookId: ID!): DeleteWebhookResponse\n updateShopProduct(\n shopId: ID!\n variantId: ID!\n productId: ID!\n price: String\n inventoryDelta: Int\n ): UpdateProductResponse\n createChannelWebhook(\n channelId: ID!\n topic: String!\n endpoint: String!\n ): CreateWebhookResponse\n deleteChannelWebhook(channelId: ID!, webhookId: ID!): DeleteWebhookResponse\n createChannelPurchase(input: CreatePurchaseInput!): CreatePurchaseResponse\n upsertMatch(data: MatchCreateInput!): Match\n }\n\n extend type Query {\n getMatch(input: [ShopItemWhereInput!]): [ChannelItemPlus!]\n getMatchCount(input: [ShopItemWhereInput!]): Int\n redirectToInit: Boolean\n searchShopProducts(shopId: ID!, searchEntry: String): [ShopProduct]\n getShopProduct(\n shopId: ID!\n variantId: String\n productId: String\n ): ShopProduct\n searchShopOrders(\n shopId: ID!\n searchEntry: String\n take: Int!\n skip: Int\n after: String\n ): ShopOrderConnection\n getShopWebhooks(shopId: ID!): [Webhook]\n searchChannelProducts(channelId: ID!, searchEntry: String): [ChannelProduct]\n getChannelProduct(\n channelId: ID!\n variantId: String\n productId: String\n ): ChannelProduct\n getChannelWebhooks(channelId: ID!): [Webhook]\n getFilteredMatches: [Match]\n }\n\n type FoundMatch {\n id: ID!\n output: [ChannelItemPlus!]\n }\n\n type ChannelItemPlus {\n quantity: Int\n productId: String\n variantId: String\n price: String\n image: String\n name: String\n channelName: String\n channelId: String\n }\n\n type ShopOrder {\n orderId: ID!\n orderName: String\n link: String\n date: String\n firstName: String\n lastName: String\n streetAddress1: String\n streetAddress2: String\n city: String\n state: String\n zip: String\n country: String\n email: String\n cartItems: [ShopCartItem]\n cursor: String\n lineItems: [ShopLineItem]\n fulfillments: [Fulfillment]\n note: String\n totalPrice: String\n }\n\n type ShopOrderConnection {\n orders: [ShopOrder]\n hasNextPage: Boolean\n }\n\n type ChannelPlus {\n id: ID!\n name: String!\n }\n\n type ShopCartItem {\n productId: String\n variantId: String\n quantity: Int\n price: String\n name: String\n image: String\n channel: ChannelPlus\n }\n\n type ShopLineItem {\n name: String\n quantity: Int\n price: String\n image: String\n productId: String\n variantId: String\n sku: String\n lineItemId: String\n }\n\n type Fulfillment {\n company: String\n number: String\n url: String\n }\n\n type Webhook {\n id: ID!\n callbackUrl: String!\n createdAt: DateTime!\n topic: String!\n includeFields: [String!]\n }\n\n type CreateWebhookResponse {\n success: Boolean\n error: String\n webhookId: ID\n }\n\n type DeleteWebhookResponse {\n success: Boolean\n error: String\n }\n\n type UpdateProductResponse {\n success: Boolean\n error: String\n updatedVariant: ProductVariant\n }\n\n type ProductVariant {\n price: String\n inventory: Int\n }\n\n input CreatePurchaseInput {\n shopId: ID!\n cartItems: [CartItemInput!]!\n email: String!\n address: AddressInput!\n orderId: ID!\n }\n\n input CartItemInput {\n variantId: ID!\n quantity: Int!\n }\n\n input AddressInput {\n firstName: String!\n lastName: String!\n streetAddress1: String!\n streetAddress2: String\n city: String!\n state: String!\n zip: String!\n country: String!\n }\n\n type CreatePurchaseResponse {\n success: Boolean\n error: String\n purchaseId: ID\n }\n`;\n\nexport const extendGraphqlSchema = (baseSchema: any) =>\n mergeSchemas({\n schemas: [baseSchema],\n typeDefs,\n resolvers: {\n Mutation: {\n addToCart,\n placeOrders,\n addMatchToCart,\n matchOrder,\n overwriteMatch,\n cancelPurchase,\n cancelOrder,\n createShopWebhook,\n deleteShopWebhook,\n updateShopProduct,\n createChannelWebhook,\n deleteChannelWebhook,\n createChannelPurchase,\n upsertMatch,\n },\n Query: {\n getMatch,\n getMatchCount,\n redirectToInit,\n searchShopProducts,\n searchShopOrders,\n getShopWebhooks,\n searchChannelProducts,\n getChannelWebhooks,\n getFilteredMatches,\n getChannelProduct,\n getShopProduct,\n },\n },\n });", "import type { KeystoneContext } from '@keystone-6/core/types';\n\ninterface AddToCartArgs {\n channelId: string;\n image?: string;\n name: string;\n price: string;\n productId: string;\n variantId: string;\n quantity: string;\n orderId: string;\n}\n\nasync function addToCart(\n root: any,\n { channelId, image, name, price, productId, variantId, quantity, orderId }: AddToCartArgs,\n context: KeystoneContext\n) {\n // 1. Query the current user see if they are signed in\n const session = context.session;\n if (!session?.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n // 2. Query the current users cart\n const allCartItems = await context.query.CartItem.findMany({\n where: {\n order: { id: { equals: orderId } },\n channel: { id: { equals: channelId } },\n user: { id: { equals: session.itemId } },\n productId: { equals: productId },\n variantId: { equals: variantId },\n status: { not: { equals: \"CANCELLED\" } },\n purchaseId: { equals: \"\" },\n url: { equals: \"\" },\n },\n query: \"id quantity\",\n });\n\n const [existingCartItem] = allCartItems;\n if (existingCartItem) {\n console.log(\n `There are already ${existingCartItem.quantity}, increment by 1!`\n );\n\n await context.query.CartItem.updateOne({\n where: { id: existingCartItem.id },\n data: {\n quantity: existingCartItem.quantity + parseInt(quantity, 10),\n },\n });\n\n return await context.db.Order.findOne({\n where: {\n id: orderId,\n },\n });\n }\n\n await context.query.CartItem.createOne({\n data: {\n price: price,\n productId,\n variantId,\n quantity: parseInt(quantity, 10),\n image,\n name,\n user: { connect: { id: session.itemId } },\n order: { connect: { id: orderId } },\n channel: { connect: { id: channelId } },\n },\n });\n\n return await context.db.Order.findOne({\n where: {\n id: orderId,\n },\n });\n}\n\nexport default addToCart;", "import type { KeystoneContext } from '@keystone-6/core/types';\n\ninterface CancelOrderArgs {\n orderId: string;\n}\n\nasync function cancelOrder(\n root: any,\n { orderId }: CancelOrderArgs,\n context: KeystoneContext\n) {\n try {\n // 1. Update order status to cancelled\n await context.query.Order.updateOne({\n where: { id: orderId },\n data: {\n status: \"CANCELLED\",\n },\n });\n\n // 2. Cancel all associated cart items\n const cartItems = await context.query.CartItem.findMany({\n where: {\n order: { id: { equals: orderId } },\n },\n query: \"id\",\n });\n\n for (const cartItem of cartItems) {\n await context.query.CartItem.updateOne({\n where: { id: cartItem.id },\n data: {\n status: \"CANCELLED\",\n },\n });\n }\n\n return \"Order cancelled successfully\";\n } catch (error: any) {\n throw new Error(`Failed to cancel order: ${error.message}`);\n }\n}\n\nexport default cancelOrder;", "import type { KeystoneContext } from '@keystone-6/core/types';\n\ninterface CancelPurchaseArgs {\n purchaseId: string;\n}\n\nasync function cancelPurchase(\n root: any,\n { purchaseId }: CancelPurchaseArgs,\n context: KeystoneContext\n) {\n try {\n // 1. Find cart items with this purchase ID\n const cartItems = await context.query.CartItem.findMany({\n where: {\n purchaseId: { equals: purchaseId },\n },\n query: \"id\",\n });\n\n // 2. Update cart items to cancelled status\n for (const cartItem of cartItems) {\n await context.query.CartItem.updateOne({\n where: { id: cartItem.id },\n data: {\n status: \"CANCELLED\",\n },\n });\n }\n\n return \"Purchase cancelled successfully\";\n } catch (error: any) {\n throw new Error(`Failed to cancel purchase: ${error.message}`);\n }\n}\n\nexport default cancelPurchase;", "\"use server\";\n\nasync function findChannelItems({ cartItems, userId, context }: {\n cartItems: Array;\n userId: string;\n context: any;\n}) {\n const arr = [];\n\n for (const {\n name,\n image,\n channelName,\n status,\n quantity,\n channelId,\n productId,\n variantId,\n price, // ensure price is string if present\n ...rest\n } of cartItems) {\n const [existingChannelItem] = await context.query.ChannelItem.findMany({\n where: {\n channel: { id: { equals: channelId } },\n user: { id: { equals: userId } },\n quantity: { equals: parseInt(quantity) },\n productId: { equals: productId },\n variantId: { equals: variantId },\n // ...rest,\n },\n });\n\n if (existingChannelItem) {\n arr.push({ id: existingChannelItem.id });\n } else {\n const createChannelItem = await context.query.ChannelItem.createOne({\n data: {\n channel: { connect: { id: channelId } },\n quantity: parseInt(quantity),\n productId,\n variantId,\n ...(price !== undefined ? { price: String(price) } : {}),\n ...rest,\n },\n });\n arr.push({ id: createChannelItem.id });\n }\n }\n\n return arr;\n}\n\nasync function findShopItems({ lineItems, userId, context }: {\n lineItems: Array;\n userId: string;\n context: any;\n}) {\n const arr = [];\n\n for (const {\n name,\n image,\n channelName,\n price, // REMOVE for ShopItem\n quantity,\n channelId,\n productId,\n variantId,\n ...rest\n } of lineItems) {\n // Remove price from rest if present\n const { price: _omitPrice, ...restWithoutPrice } = rest;\n const [existingShopItem] = await context.query.ShopItem.findMany({\n where: {\n shop: { id: { equals: channelId } },\n user: { id: { equals: userId } },\n quantity: { equals: parseInt(quantity) },\n productId: { equals: productId },\n variantId: { equals: variantId },\n ...restWithoutPrice,\n },\n });\n\n if (existingShopItem) {\n arr.push({ id: existingShopItem.id });\n } else {\n const createShopItem = await context.query.ShopItem.createOne({\n data: {\n shop: { connect: { id: channelId } },\n quantity: parseInt(quantity),\n productId,\n variantId,\n ...restWithoutPrice,\n },\n });\n arr.push({ id: createShopItem.id });\n }\n }\n\n return arr;\n}\n\nasync function matchOrder(root: any, { orderId }: { orderId: string }, context: any) {\n const sesh = context.session;\n\n if (!sesh.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n const order = await context.query.Order.findOne({\n where: {\n id: orderId,\n },\n query: `\n cartItems {\n channel {\n id\n }\n image\n price\n id\n quantity\n productId\n variantId\n }\n shop {\n id\n }\n lineItems {\n image\n price\n id\n quantity\n productId\n variantId\n lineItemId\n }\n `,\n });\n\n const shopItemConnect = await findShopItems({\n lineItems: order.lineItems.map(\n ({ id, lineItemId, orderId, userId, updatedAt, createdAt, ...rest }: any) => {\n // turn into NullFilter values ({ equal }) for findMany\n // const restNested = Object.keys(rest).reduce(\n // (acc, key) => ({\n // ...acc,\n // ...{ [key]: { equals: rest[key] } },\n // }),\n // {}\n // );\n return {\n ...rest,\n channelId: order.shop.id,\n };\n }\n ),\n userId: sesh.itemId,\n context,\n });\n\n const channelItemConnect = await findChannelItems({\n cartItems: order.cartItems.map(\n ({\n id,\n lineItemId,\n orderId,\n userId,\n updatedAt,\n createdAt,\n url,\n error: cartItemError,\n purchaseId,\n channel,\n ...rest\n }: any) => {\n return {\n ...rest,\n channelId: channel.id,\n };\n }\n ),\n userId: sesh.itemId,\n context,\n });\n\n const existingMatches = await context.query.Match.findMany({\n where: {\n user: {\n id: { equals: sesh.itemId },\n },\n AND: order.lineItems.map(({ productId, variantId, quantity }: any) => ({\n input: {\n some: {\n productId: { equals: productId },\n variantId: { equals: variantId },\n quantity: { equals: parseInt(quantity) },\n },\n },\n })),\n },\n query: ` \n id\n inputCount\n outputCount\n input {\n id\n quantity\n productId\n variantId\n shop {\n id\n }\n user {\n id\n }\n }\n output {\n id\n quantity\n productId\n variantId\n price\n channel {\n id\n domain\n accessToken\n platform {\n id\n }\n }\n user {\n id\n }\n }\n `,\n });\n\n const [existingMatch] = existingMatches.filter(\n (match: any) => match.input.length === order.lineItems.length\n );\n\n if (existingMatch) {\n await context.query.Match.deleteOne({\n where: { id: existingMatch.id },\n });\n }\n\n const newMatch = await context.db.Match.createOne({\n data: {\n input: { connect: shopItemConnect },\n output: { connect: channelItemConnect },\n user: {\n connect: {\n id: sesh.itemId,\n },\n },\n },\n });\n\n return newMatch;\n}\n\nexport default matchOrder;", "import type { KeystoneContext } from '@keystone-6/core/types';\n\ninterface OverwriteMatchArgs {\n input: Array<{\n productId?: string;\n variantId?: string;\n [key: string]: any;\n }>;\n output: Array<{\n productId?: string;\n variantId?: string;\n [key: string]: any;\n }>;\n}\n\nasync function overwriteMatch(\n root: any,\n { input, output }: OverwriteMatchArgs,\n context: KeystoneContext\n) {\n // 1. Query the current user see if they are signed in\n const session = context.session;\n if (!session?.itemId) {\n throw new Error(\"You must be logged in to do this!\");\n }\n\n // 2. Find existing match with same input criteria\n const existingMatches = await context.query.Match.findMany({\n where: {\n input: {\n every: {\n OR: input.map(item => ({\n AND: [\n { productId: { equals: item.productId } },\n { variantId: { equals: item.variantId } }\n ]\n }))\n }\n }\n },\n query: \"id\",\n });\n\n // 3. Delete existing matches\n for (const match of existingMatches) {\n await context.query.Match.deleteOne({\n where: { id: match.id },\n });\n }\n\n // 4. Create new match\n const match = await context.query.Match.createOne({\n data: {\n user: { connect: { id: session.itemId } },\n input: {\n create: input.map(item => ({\n productId: item.productId,\n variantId: item.variantId,\n user: { connect: { id: session.itemId } },\n }))\n },\n output: {\n create: output.map(item => ({\n productId: item.productId,\n variantId: item.variantId,\n price: item.price,\n quantity: item.quantity,\n name: item.name,\n image: item.image,\n channel: { connect: { id: item.channelId } },\n user: { connect: { id: session.itemId } },\n }))\n }\n },\n query: \"id\",\n });\n\n return match;\n}\n\nexport default overwriteMatch;", "import { placeMultipleOrders } from '../../lib/placeMultipleOrders';\n\nasync function placeOrders(root: any, { ids }: { ids: string[] }, context: any) {\n // 1. Query the current user see if they are signed in\n const sesh = context.session;\n if (!sesh.itemId) {\n throw new Error('You must be logged in to do this!');\n }\n\n const processedOrders = await placeMultipleOrders({\n ids,\n query: context.query,\n });\n\n return processedOrders;\n}\n\nexport default placeOrders;", "import { createShopWebhook as executeCreateShopWebhook } from \"../../utils/shopProviderAdapter\";\n\ninterface CreateShopWebhookArgs {\n shopId: string;\n topic: string;\n endpoint: string;\n}\n\nasync function createShopWebhook(\n root: any,\n { shopId, topic, endpoint }: CreateShopWebhookArgs,\n context: any\n) {\n\n try {\n const sudoContext = context.sudo();\n\n \n // Fetch the shop using the provided shopId\n const shop = await sudoContext.query.Shop.findOne({\n where: { id: shopId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n name\n createWebhookFunction\n }\n `,\n });\n\n\n if (!shop) {\n return { success: false, error: \"Shop not found\" };\n }\n\n if (!shop.platform) {\n return { success: false, error: \"Platform configuration not specified.\" };\n }\n\n if (!shop.platform.createWebhookFunction) {\n return { success: false, error: \"Create webhook function not configured.\" };\n }\n\n // Prepare platform configuration (matching getShopProduct pattern)\n const platformConfig = {\n domain: shop.domain,\n accessToken: shop.accessToken,\n createWebhookFunction: shop.platform.createWebhookFunction,\n ...shop.metadata,\n };\n\n const result = await executeCreateShopWebhook({\n platform: platformConfig,\n endpoint,\n events: [topic],\n });\n\n\n return { success: true, webhookId: result.webhookId };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n}\n\nexport default createShopWebhook;", "import { deleteShopWebhook as executeDeleteShopWebhook } from \"../../utils/shopProviderAdapter\";\n\ninterface DeleteShopWebhookArgs {\n shopId: string;\n webhookId: string;\n}\n\nasync function deleteShopWebhook(\n root: any,\n { shopId, webhookId }: DeleteShopWebhookArgs,\n context: any\n) {\n try {\n // Fetch the shop using the provided shopId\n const shop = await context.query.Shop.findOne({\n where: { id: shopId },\n query: \"id domain accessToken platform { id deleteWebhookFunction }\",\n });\n\n if (!shop) {\n return { success: false, error: \"Shop not found\" };\n }\n\n if (!shop.platform) {\n return { success: false, error: \"Platform configuration not specified.\" };\n }\n\n await executeDeleteShopWebhook({\n platform: {\n ...shop.platform,\n domain: shop.domain,\n accessToken: shop.accessToken,\n },\n webhookId,\n });\n\n return { success: true };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n}\n\nexport default deleteShopWebhook;", "import { updateShopProduct as executeUpdateShopProduct } from \"../../utils/shopProviderAdapter\";\n\nasync function updateShopProduct(\n root: any,\n { shopId, variantId, productId, price, inventoryDelta }: {\n shopId: string;\n variantId: string;\n productId: string;\n price?: string;\n inventoryDelta?: number;\n },\n context: any\n) {\n // Fetch the shop using the provided shopId\n const shop = await context.query.Shop.findOne({\n where: { id: shopId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n updateProductFunction\n }\n `,\n });\n\n if (!shop) {\n throw new Error(\"Shop not found\");\n }\n\n if (!shop.platform) {\n throw new Error(\"Platform configuration not specified.\");\n }\n\n // Create platform config with domain, accessToken, and metadata\n const platformConfig = {\n domain: shop.domain,\n accessToken: shop.accessToken,\n ...shop.metadata,\n };\n\n try {\n const result = await executeUpdateShopProduct({\n platform: {\n ...shop.platform,\n ...platformConfig,\n },\n productId,\n variantId,\n inventory: inventoryDelta,\n price,\n });\n\n if (result.error) {\n throw new Error(result.error);\n }\n\n return { success: true, updatedVariant: result.updatedVariant };\n } catch (error: any) {\n throw new Error(`Failed to update product: ${error.message}`);\n }\n}\n\nexport default updateShopProduct;", "import { createChannelWebhook as executeCreateChannelWebhook } from \"../../utils/channelProviderAdapter\";\n\ninterface CreateChannelWebhookArgs {\n channelId: string;\n topic: string;\n endpoint: string;\n}\n\nasync function createChannelWebhook(\n root: any,\n { channelId, topic, endpoint }: CreateChannelWebhookArgs,\n context: any\n) {\n try {\n const sudoContext = context.sudo();\n\n // Fetch the channel using the provided channelId\n const channel = await sudoContext.query.Channel.findOne({\n where: { id: channelId },\n query: `\n id\n domain\n accessToken\n metadata\n platform {\n id\n name\n createWebhookFunction\n }\n `,\n });\n\n if (!channel) {\n return { success: false, error: \"Channel not found\" };\n }\n\n if (!channel.platform) {\n return { success: false, error: \"Platform configuration not specified.\" };\n }\n\n if (!channel.platform.createWebhookFunction) {\n return { success: false, error: \"Create webhook function not configured.\" };\n }\n\n // Prepare platform configuration (matching working pattern)\n const platformConfig = {\n domain: channel.domain,\n accessToken: channel.accessToken,\n createWebhookFunction: channel.platform.createWebhookFunction,\n ...channel.metadata,\n };\n\n const result = await executeCreateChannelWebhook({\n platform: platformConfig,\n endpoint,\n events: [topic],\n });\n\n return { success: true, webhookId: result.webhookId };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n}\n\nexport default createChannelWebhook;", "import { deleteChannelWebhook as executeDeleteChannelWebhook } from \"../../utils/channelProviderAdapter\";\n\ninterface DeleteChannelWebhookArgs {\n channelId: string;\n webhookId: string;\n}\n\nasync function deleteChannelWebhook(\n root: any,\n { channelId, webhookId }: DeleteChannelWebhookArgs,\n context: any\n) {\n try {\n // Fetch the channel using the provided channelId\n const channel = await context.query.Channel.findOne({\n where: { id: channelId },\n query: \"id domain accessToken platform { id deleteWebhookFunction }\",\n });\n\n if (!channel) {\n return { success: false, error: \"Channel not found\" };\n }\n\n if (!channel.platform) {\n return { success: false, error: \"Platform configuration not specified.\" };\n }\n\n await executeDeleteChannelWebhook({\n platform: {\n ...channel.platform,\n domain: channel.domain,\n accessToken: channel.accessToken,\n },\n webhookId,\n });\n\n return { success: true };\n } catch (error: any) {\n return { success: false, error: error.message };\n }\n}\n\nexport default deleteChannelWebhook;", "import { createChannelPurchase as executeChannelPurchase } from \"../../utils/channelProviderAdapter\";\n\nasync function createChannelPurchase(root: any, { input }: { input: any }, context: any) {\n const { channelId, cartItems, address, notes, ...otherData } = input;\n\n // Fetch the channel using the provided channelId\n const channel = await context.query.Channel.findOne({\n where: { id: channelId },\n query: \"id domain accessToken platform { id createPurchaseFunction }\",\n });\n\n if (!channel) {\n throw new Error(\"Channel not found\");\n }\n\n if (!channel.platform) {\n throw new Error(\"Channel platform not configured.\");\n }\n\n try {\n const result = await executeChannelPurchase({\n platform: channel.platform,\n cartItems,\n shipping: address,\n notes,\n });\n\n if (result.error) {\n throw new Error(result.error);\n }\n\n return { success: true, purchaseId: result.purchaseId };\n } catch (error: any) {\n throw new Error(`Failed to create purchase: ${error.message}`);\n }\n}\n\nexport default createChannelPurchase;", "const upsertMatch = async (_: any, { data }: { data: any }, context: any) => {\n const { input, output } = data;\n // Ensure ShopItems\n const ensureShopItems = async (items: any[]) => {\n const processedItems = [];\n for (const item of items) {\n let [existingItem] = await context.query.ShopItem.findMany({\n where: {\n productId: { equals: item.productId },\n variantId: { equals: item.variantId },\n quantity: { equals: item.quantity },\n shop: { id: { equals: item.shop.connect.id } },\n user: { id: { equals: item.user?.connect?.id || context.session?.itemId } },\n },\n query: \"id\",\n });\n\n if (!existingItem) {\n existingItem = await context.db.ShopItem.createOne({\n data: item,\n query: \"id\",\n });\n }\n\n processedItems.push({ id: existingItem.id });\n }\n return processedItems;\n };\n\n // Ensure ChannelItems\n const ensureChannelItems = async (items: any[]) => {\n const processedItems = [];\n for (const item of items) {\n let [existingItem] = await context.query.ChannelItem.findMany({\n where: {\n productId: { equals: item.productId },\n variantId: { equals: item.variantId },\n quantity: { equals: item.quantity },\n channel: { id: { equals: item.channel.connect.id } },\n user: { id: { equals: item.user?.connect?.id || context.session?.itemId } },\n },\n query: \"id\",\n });\n\n if (!existingItem) {\n existingItem = await context.query.ChannelItem.createOne({\n data: item,\n query: \"id\",\n });\n }\n\n processedItems.push({ id: existingItem.id });\n }\n return processedItems;\n };\n\n // Process inputs and outputs\n const processedInput = await ensureShopItems(input.create);\n const processedOutput = await ensureChannelItems(output.create);\n\n const inputIds = processedInput.map((item) => item.id);\n const outputIds = processedOutput.map((item) => item.id);\n\n // Check for existing match\n const existingMatches = await context.query.Match.findMany({\n where: {\n input: {\n some: { id: { in: inputIds } },\n },\n },\n query: \"id input { id } output { id }\",\n });\n\n const duplicateMatch = existingMatches.find((match: any) => {\n const matchInputIds = match.input.map((i: any) => i.id);\n return (\n matchInputIds.length === inputIds.length &&\n matchInputIds.every((id: string) => inputIds.includes(id))\n );\n });\n\n if (duplicateMatch) {\n // Update existing match\n await context.query.Match.updateOne({\n where: { id: duplicateMatch.id },\n data: {\n output: {\n disconnect: duplicateMatch.output.map((o: any) => ({ id: o.id })),\n connect: outputIds.map((id) => ({ id })),\n },\n },\n });\n return duplicateMatch;\n } else {\n // Create new match\n return await context.query.Match.createOne({\n data: {\n input: { connect: inputIds.map((id) => ({ id })) },\n output: { connect: outputIds.map((id) => ({ id })) },\n },\n });\n }\n};\n\nexport default upsertMatch;", "'use server' \n\nimport { createTransport, getTestMessageUrl } from \"nodemailer\";\n\n// Utility function to get base URL for emails\nfunction getBaseUrlForEmails(): string {\n if (process.env.SMTP_STORE_LINK) {\n return process.env.SMTP_STORE_LINK;\n }\n \n // Fallback warning - this should be set in production\n console.warn('SMTP_STORE_LINK not set. Please add SMTP_STORE_LINK to your environment variables for email links to work properly.');\n return '';\n}\n\nconst transport = createTransport({\n // @ts-ignore\n host: process.env.SMTP_HOST,\n port: process.env.SMTP_PORT,\n auth: {\n user: process.env.SMTP_USER,\n pass: process.env.SMTP_PASSWORD,\n },\n});\n\nfunction passwordResetEmail({ url }: { url: string }): string {\n const backgroundColor = \"#f9f9f9\";\n const textColor = \"#444444\";\n const mainBackgroundColor = \"#ffffff\";\n const buttonBackgroundColor = \"#346df1\";\n const buttonBorderColor = \"#346df1\";\n const buttonTextColor = \"#ffffff\";\n\n return `\n \n \n \n \n \n \n \n \n \n \n \n
\n Please click below to reset your password\n
\n \n \n \n \n
Reset Password
\n
\n If you did not request this email you can safely ignore it.\n
\n \n `;\n}\n\nexport async function sendPasswordResetEmail(resetToken: string, to: string, baseUrl?: string): Promise {\n // Use provided baseUrl or fall back to utility function\n const frontendUrl = baseUrl || getBaseUrlForEmails();\n \n // email the user a token\n const info = await transport.sendMail({\n to,\n from: process.env.SMTP_FROM,\n subject: \"Your password reset token!\",\n html: passwordResetEmail({\n url: `${frontendUrl}/dashboard/reset?token=${resetToken}`,\n }),\n });\n if (process.env.MAIL_USER?.includes(\"ethereal.email\")) {\n console.log(`\uD83D\uDCE7 Message Sent! Preview it at ${getTestMessageUrl(info as any)}`);\n }\n}"], + "mappings": "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", + "names": ["scopes", "createPurchaseFunction", "createWebhookFunction", "deleteWebhookFunction", "getProductFunction", "getWebhooksFunction", "oAuthCallbackFunction", "oAuthFunction", "scopes", "searchProductsFunction", "REQUIRED_SCOPES", "import_graphql_request", "openfront_exports", "addTrackingFunction", "createWebhookFunction", "deleteWebhookFunction", "getProductFunction", "getWebhooksFunction", "oAuthCallbackFunction", "oAuthFunction", "scopes", "searchProductsFunction", "createOpenFrontClient", "getProductImageUrl", "REQUIRED_SCOPES", "import_graphql_request", "import_context", "getFreshAccessToken", "init_openfront", "shopify_exports", "addTrackingFunction", "cancelOrderWebhookHandler", "createOrderWebhookHandler", "createWebhookFunction", "deleteWebhookFunction", "getProductFunction", "getWebhooksFunction", "oAuthCallbackFunction", "oAuthFunction", "scopes", "searchOrdersFunction", "searchProductsFunction", "updateProductFunction", "REQUIRED_SCOPES", "import_graphql_request", "import_getBaseUrl", "init_shopify", "executor_exports", "globImport_ts", "init_executor", "init_", "keystone_default", "import_core", "import_fields", "scopes", "permissions", "import_fields", "import_core", "import_fields", "import_core", "import_fields", "import_core", "import_fields", "executeChannelAdapterFunction", "searchChannelProducts", "getChannelProduct", "createChannelPurchase", "createChannelWebhook", "deleteChannelWebhook", "getChannelWebhooks", "executeShopAdapterFunction", "searchShopProducts", "getShopProduct", "searchShopOrders", "updateShopProduct", "addCartToPlatformOrder", "createShopWebhook", "deleteShopWebhook", "getShopWebhooks", "createChannelPurchase", "addCartToPlatformOrder", "order", "import_core", "import_fields", "addShopTracking", "import_core", "import_fields", "import_core", "import_fields", "import_core", "import_fields", "executeChannelAdapterFunction", "import_fields", "import_core", "getMatches", "searchProductsFunction", "searchChannelProducts", "getMatches", "getShopWebhooks", "searchShopOrders", "searchShopProducts", "searchChannelProducts", "getChannelWebhooks", "getChannelProduct", "getShopProduct", "import_core", "import_fields", "executeShopAdapterFunction", "import_fields", "import_core", "import_core", "import_fields", "item", "input", "import_core", "import_fields", "import_core", "import_fields", "import_core", "import_fields", "orderId", "match", "createShopWebhook", "deleteShopWebhook", "updateShopProduct", "createChannelWebhook", "deleteChannelWebhook", "createChannelPurchase", "graphql", "Iron", "bcryptjs", "keystone_default"] } diff --git a/README.md b/README.md index 2656f1c..b369419 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,7 @@ openship/ ## Documentation -For comprehensive technical documentation, see [docs.openship.org/openship/ecommerce](https://docs.openship.org/openship/ecommerce) which covers: +For comprehensive technical documentation, see [docs.openship.org/docs/openship/ecommerce](https://docs.openship.org/docs/openship/ecommerce) which covers: - Complete integration guides - API reference and operations - Custom shop and channel development @@ -176,15 +176,6 @@ Openship is production-ready and can be deployed to: - Webhook reliability and retry mechanisms - Monitoring and alerting for failed orders -## Foundation - -This project is built on [next-keystone-starter](https://github.com/junaid33/next-keystone-starter), which provides: -- Modern full-stack architecture -- KeystoneJS 6 integration with Next.js 15 -- Authentication and session management -- Database setup with Prisma -- Development tooling and configuration - ## Contributing We welcome contributions! Please see our contributing guidelines for details on: @@ -199,7 +190,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file ## Support -- **Documentation**: Check our comprehensive documentation at [docs.openship.org/openship/ecommerce](https://docs.openship.org/openship/ecommerce) +- **Documentation**: Check our comprehensive documentation at [docs.openship.org/docs/openship/ecommerce](https://docs.openship.org/docs/openship/ecommerce) - **Issues**: Report bugs and feature requests on GitHub Issues - **Community**: Join our community discussions - **Enterprise**: Contact us for enterprise support and custom integrations @@ -207,4 +198,4 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file --- **Openship** - Order Routing Platform -Built with Next.js 15 and KeystoneJS 6 on [next-keystone-starter](https://github.com/junaid33/next-keystone-starter) \ No newline at end of file +Built with Next.js 15 and KeystoneJS 6 \ No newline at end of file diff --git a/app/api/oauth/callback/route.ts b/app/api/oauth/callback/route.ts index 6735565..08bc8ce 100644 --- a/app/api/oauth/callback/route.ts +++ b/app/api/oauth/callback/route.ts @@ -38,6 +38,9 @@ async function generateOAuthState(platformId: string, type: 'shop' | 'channel'): export async function GET(request: NextRequest) { try { + console.log('🚀 OAuth callback endpoint called'); + console.log('🔍 Request URL:', request.url); + const { searchParams } = new URL(request.url); // Get OAuth parameters @@ -51,6 +54,16 @@ export async function GET(request: NextRequest) { const autoCreate = searchParams.get('auto_create') === 'true'; const appName = searchParams.get('app_name'); const clientId = searchParams.get('client_id'); + + console.log('🔍 OAuth callback parameters:'); + console.log(' - code:', code ? `${code.substring(0, 10)}...` : 'MISSING'); + console.log(' - state:', state ? `${state.substring(0, 20)}...` : 'MISSING'); + console.log(' - shop:', shop); + console.log(' - error:', error); + console.log(' - errorDescription:', errorDescription); + console.log(' - autoCreate:', autoCreate); + console.log(' - appName:', appName); + console.log(' - clientId:', clientId); // Handle OAuth errors if (error) { @@ -168,14 +181,24 @@ export async function GET(request: NextRequest) { redirectUri: `${await getBaseUrl()}/api/oauth/callback` }); + console.log('🔍 Token exchange result type:', typeof tokenResult); + console.log('🔍 Token exchange result:', typeof tokenResult === 'string' ? `${tokenResult.substring(0, 10)}...` : tokenResult); + // Handle both old string format and new object format let accessToken, refreshToken, tokenExpiresAt; if (typeof tokenResult === 'string') { + console.log('📝 Using legacy string token format'); accessToken = tokenResult; } else { - accessToken = tokenResult.access_token; - refreshToken = tokenResult.refresh_token; - tokenExpiresAt = tokenResult.expires_at; + console.log('📝 Using new object token format'); + // OpenFront returns camelCase field names + accessToken = tokenResult.accessToken; + refreshToken = tokenResult.refreshToken; + tokenExpiresAt = tokenResult.tokenExpiresAt; + console.log('🔑 Token details:'); + console.log(' - accessToken present:', !!accessToken); + console.log(' - refreshToken present:', !!refreshToken); + console.log(' - tokenExpiresAt present:', !!tokenExpiresAt); } const baseUrl = await getBaseUrl(); @@ -185,6 +208,12 @@ export async function GET(request: NextRequest) { const endpoint = redirectAppType === 'channel' ? 'channels' : 'shops'; const createParam = redirectAppType === 'channel' ? 'showCreateChannel' : 'showCreateShop'; + console.log('🎯 Building redirect URL:'); + console.log(' - baseUrl:', baseUrl); + console.log(' - redirectAppType:', redirectAppType); + console.log(' - endpoint:', endpoint); + console.log(' - createParam:', createParam); + const redirectUrl = new URL(`${baseUrl}/dashboard/platform/${endpoint}`); redirectUrl.searchParams.set(createParam, 'true'); redirectUrl.searchParams.set('domain', shop ?? ''); @@ -193,13 +222,24 @@ export async function GET(request: NextRequest) { redirectUrl.searchParams.set('client_secret', stateData.client_secret); redirectUrl.searchParams.set('app_name', stateData.app_name); redirectUrl.searchParams.set('adapter_slug', stateData.adapter_slug); + + console.log('🔑 Adding optional tokens to redirect:'); if (refreshToken) { + console.log(' - Adding refreshToken to URL params'); redirectUrl.searchParams.set('refreshToken', refreshToken); + } else { + console.log(' - No refreshToken to add'); } if (tokenExpiresAt) { - redirectUrl.searchParams.set('tokenExpiresAt', tokenExpiresAt.toISOString()); + console.log(' - Adding tokenExpiresAt to URL params:', tokenExpiresAt); + // tokenExpiresAt is already a string from OpenFront adapter + redirectUrl.searchParams.set('tokenExpiresAt', tokenExpiresAt); + } else { + console.log(' - No tokenExpiresAt to add'); } + console.log('🎯 Final redirect URL:', redirectUrl.toString()); + return NextResponse.redirect(redirectUrl.toString()); } @@ -254,7 +294,7 @@ export async function GET(request: NextRequest) { accessToken = tokenResult; } else { // New format - object with both tokens - accessToken = tokenResult.access_token; + accessToken = tokenResult.accessToken; } // Redirect to shops page with params @@ -264,8 +304,12 @@ export async function GET(request: NextRequest) { redirectUrl.searchParams.set('accessToken', accessToken); if (typeof tokenResult === 'object') { // Include additional token data for new implementations - redirectUrl.searchParams.set('refreshToken', tokenResult.refresh_token); - redirectUrl.searchParams.set('tokenExpiresAt', tokenResult.expires_at.toISOString()); + if (tokenResult.refreshToken) { + redirectUrl.searchParams.set('refreshToken', tokenResult.refreshToken); + } + if (tokenResult.tokenExpiresAt) { + redirectUrl.searchParams.set('tokenExpiresAt', tokenResult.tokenExpiresAt); + } } redirectUrl.searchParams.set('domain', shop ?? ''); @@ -288,7 +332,7 @@ export async function GET(request: NextRequest) { } // Exchange code for access token - accessToken = await handleChannelOAuthCallback({ + const channelTokenResult = await handleChannelOAuthCallback({ platform, code, shop: shop || undefined, @@ -298,11 +342,29 @@ export async function GET(request: NextRequest) { redirectUri: `${baseUrl}/api/oauth/callback`, // Single callback URL }); + // Handle both old string format and new object format for backward compatibility + if (typeof channelTokenResult === 'string') { + // Legacy format - just access token + accessToken = channelTokenResult; + } else { + // New format - object with both tokens + accessToken = channelTokenResult.accessToken; + } + // Redirect to channels page with params const redirectUrl = new URL(`${baseUrl}/dashboard/platform/channels`); redirectUrl.searchParams.set('showCreateChannel', 'true'); redirectUrl.searchParams.set('platform', platformId); redirectUrl.searchParams.set('accessToken', accessToken); + if (typeof channelTokenResult === 'object') { + // Include additional token data for new implementations + if (channelTokenResult.refreshToken) { + redirectUrl.searchParams.set('refreshToken', channelTokenResult.refreshToken); + } + if (channelTokenResult.tokenExpiresAt) { + redirectUrl.searchParams.set('tokenExpiresAt', channelTokenResult.tokenExpiresAt); + } + } redirectUrl.searchParams.set('domain', shop ?? ''); return NextResponse.redirect(redirectUrl.toString()); diff --git a/components/ui/datetime-picker.tsx b/components/ui/datetime-picker.tsx new file mode 100644 index 0000000..2ce6e8c --- /dev/null +++ b/components/ui/datetime-picker.tsx @@ -0,0 +1,134 @@ +"use client"; + +import * as React from "react"; +import { format } from "date-fns"; +import { CalendarIcon } from "lucide-react"; + +import { cn } from "@/lib/utils"; +import { Button } from "@/components/ui/button"; +import { Calendar } from "@/components/ui/calendar"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { Input } from "@/components/ui/input"; +import { Label } from "@/components/ui/label"; + +interface DateTimePickerProps { + value?: string; + onChange?: (value: string) => void; + placeholder?: string; + className?: string; + disabled?: boolean; +} + +export function DateTimePicker({ + value, + onChange, + placeholder = "Pick a date and time", + className, + disabled = false, +}: DateTimePickerProps) { + const [date, setDate] = React.useState( + value ? new Date(value) : undefined + ); + const [time, setTime] = React.useState( + value ? format(new Date(value), "HH:mm") : "" + ); + const [open, setOpen] = React.useState(false); + + const handleDateSelect = (selectedDate: Date | undefined) => { + if (selectedDate) { + const newDate = new Date(selectedDate); + if (time) { + const [hours, minutes] = time.split(":"); + newDate.setHours(parseInt(hours), parseInt(minutes)); + } + setDate(newDate); + const isoString = newDate.toISOString().slice(0, 16); // YYYY-MM-DDTHH:mm format + onChange?.(isoString); + } + }; + + const handleTimeChange = (newTime: string) => { + setTime(newTime); + if (date && newTime) { + const [hours, minutes] = newTime.split(":"); + const newDate = new Date(date); + newDate.setHours(parseInt(hours), parseInt(minutes)); + setDate(newDate); + const isoString = newDate.toISOString().slice(0, 16); // YYYY-MM-DDTHH:mm format + onChange?.(isoString); + } + }; + + const handleClear = () => { + setDate(undefined); + setTime(""); + onChange?.(""); + setOpen(false); + }; + + return ( + + + + + +
+ +
+ + handleTimeChange(e.target.value)} + className="w-full" + /> +
+
+ + +
+
+
+
+ ); +} \ No newline at end of file diff --git a/components/ui/multiselect.tsx b/components/ui/multiselect.tsx index 2982966..49f16e2 100644 --- a/components/ui/multiselect.tsx +++ b/components/ui/multiselect.tsx @@ -444,7 +444,7 @@ const MultipleSelector = ({ inputRef?.current?.focus() }} > -
+
{selected.map((option) => { return (
{open && ( { setOnScrollbar(false) }} diff --git a/features/integrations/channel/openfront.ts b/features/integrations/channel/openfront.ts index dc295c0..664cfd9 100644 --- a/features/integrations/channel/openfront.ts +++ b/features/integrations/channel/openfront.ts @@ -1,4 +1,5 @@ import { GraphQLClient, gql } from "graphql-request"; +import { keystoneContext } from '@/features/keystone/context'; interface OpenFrontPlatform { domain: string; @@ -36,46 +37,132 @@ interface DeleteWebhookArgs { // Helper function to get fresh access token with proper OAuth 2.0 flow const getFreshAccessToken = async (platform: OpenFrontPlatform) => { - // Check if we have local access token expiry information - if (platform.tokenExpiresAt && platform.refreshToken) { - const expiresAt = typeof platform.tokenExpiresAt === 'string' - ? new Date(platform.tokenExpiresAt) - : platform.tokenExpiresAt; + console.log('🔄 [OpenFront Channel] getFreshAccessToken called'); + console.log('🔄 [OpenFront Channel] Platform domain:', platform.domain); + console.log('🔄 [OpenFront Channel] Actual access token:', platform.accessToken); + + // Get channel with OAuth credentials from database + const channels = await keystoneContext.sudo().query.Channel.findMany({ + where: { + domain: { equals: platform.domain }, + accessToken: { equals: platform.accessToken } + }, + query: 'id refreshToken tokenExpiresAt platform { appKey appSecret }' + }); + + if (!channels || channels.length === 0) { + console.log('⚠️ [OpenFront Channel] No matching channel found in database'); + return platform.accessToken; + } + + const channel = channels[0]; + console.log('🔄 [OpenFront Channel] Found channel:', channel.id); + console.log('🔄 [OpenFront Channel] Has refresh token:', !!channel.refreshToken); + console.log('🔄 [OpenFront Channel] Token expires at:', channel.tokenExpiresAt); + console.log('🔄 [OpenFront Channel] Has appKey:', !!channel.platform?.appKey); + console.log('🔄 [OpenFront Channel] Has appSecret:', !!channel.platform?.appSecret); + console.log('🔄 [OpenFront Channel] Actual refresh token:', channel.refreshToken); + + // If we have a refresh token, check if we need to refresh + if (channel.refreshToken) { + console.log('🔄 [OpenFront Channel] Refresh token found, checking if refresh needed'); - // If access token hasn't expired yet, use it - if (expiresAt > new Date()) { - return platform.accessToken; + // Check if access token has expired (if we have expiry info) + let shouldRefresh = false; + + if (channel.tokenExpiresAt) { + const expiresAt = typeof channel.tokenExpiresAt === 'string' + ? new Date(channel.tokenExpiresAt) + : channel.tokenExpiresAt; + + const now = new Date(); + shouldRefresh = expiresAt <= now; + + console.log('🔄 [OpenFront Channel] Token expiry check:'); + console.log('🔄 [OpenFront Channel] - Expires at:', expiresAt.toISOString()); + console.log('🔄 [OpenFront Channel] - Current time:', now.toISOString()); + console.log('🔄 [OpenFront Channel] - Should refresh:', shouldRefresh); + } else { + // If no expiry info, assume token needs refresh + shouldRefresh = true; + console.log('🔄 [OpenFront Channel] No expiry info found, assuming refresh needed'); } - // Use refresh token to get new access token + if (shouldRefresh) { + console.log('🔄 [OpenFront Channel] Starting token refresh process...'); + + // Use refresh token to get new access token const tokenUrl = `${platform.domain}/api/oauth/token`; + console.log('🔄 [OpenFront Channel] Token URL:', tokenUrl); const formData = new URLSearchParams({ grant_type: "refresh_token", - refresh_token: platform.refreshToken, + refresh_token: channel.refreshToken, + client_id: channel.platform?.appKey || "", + client_secret: channel.platform?.appSecret || "", }); + console.log('🔄 [OpenFront Channel] Refresh request params:'); + console.log('🔄 [OpenFront Channel] - grant_type: refresh_token'); + console.log('🔄 [OpenFront Channel] - client_id:', channel.platform?.appKey || "NOT_SET"); + console.log('🔄 [OpenFront Channel] - client_secret:', channel.platform?.appSecret ? "SET" : "NOT_SET"); + console.log('🔄 [OpenFront Channel] - refresh_token:', channel.refreshToken ? "SET" : "NOT_SET"); + + console.log('🔄 [OpenFront Channel] Making refresh token request...'); const response = await fetch(tokenUrl, { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: formData, }); + console.log('🔄 [OpenFront Channel] Refresh response status:', response.status); + console.log('🔄 [OpenFront Channel] Refresh response ok:', response.ok); + if (!response.ok) { const errorText = await response.text(); - console.error('Token refresh failed:', errorText); + console.error('🚨 [OpenFront Channel] Token refresh failed:', errorText); + console.error('🚨 [OpenFront Channel] Response status:', response.status); + console.error('🚨 [OpenFront Channel] Response statusText:', response.statusText); throw new Error(`Failed to refresh access token: ${response.statusText} - ${errorText}`); } - const { access_token } = await response.json(); + const tokenData = await response.json(); + console.log('🔄 [OpenFront Channel] Token refresh response received'); + console.log('🔄 [OpenFront Channel] - Has access_token:', !!tokenData.access_token); + console.log('🔄 [OpenFront Channel] - Has refresh_token:', !!tokenData.refresh_token); + console.log('🔄 [OpenFront Channel] - Expires in:', tokenData.expires_in, 'seconds'); - // TODO: Update stored access token and expiry in database - // This would require updating the shop/channel record with new tokens + const { access_token, refresh_token, expires_in } = tokenData; + // Update stored access token and expiry in database + console.log('🔄 [OpenFront Channel] Updating tokens in database...'); + try { + console.log('🔄 [OpenFront Channel] Updating channel:', channel.id); + await keystoneContext.sudo().query.Channel.updateOne({ + where: { id: channel.id }, + data: { + accessToken: access_token, + ...(refresh_token && { refreshToken: refresh_token }), + ...(expires_in && { tokenExpiresAt: new Date(Date.now() + (expires_in * 1000)) }) + } + }); + console.log('✅ [OpenFront Channel] Channel updated with new tokens:', channel.id); + } catch (error) { + console.error('🚨 [OpenFront Channel] Failed to update channel tokens in database:', error); + // Continue with the request even if database update fails + } + + console.log('✅ [OpenFront Channel] Returning fresh access token'); return access_token; + } else { + // Token hasn't expired yet, use existing one + console.log('✅ [OpenFront Channel] Token still valid, using existing access token'); + return platform.accessToken; + } } - // If no refresh capability, just use the access token as-is + // If no refresh token, just use the access token as-is + console.log('⚠️ [OpenFront Channel] No refresh token available, using existing access token'); return platform.accessToken; }; @@ -229,7 +316,7 @@ export async function getProductFunction({ const openFrontClient = await createOpenFrontClient(platform); const gqlQuery = gql` - query GetChannelProduct($productId: ID!, $variantId: ID) { + query GetChannelProduct($productId: ID!, $variantWhere: ProductVariantWhereInput) { product(where: { id: $productId }) { id title @@ -240,7 +327,7 @@ export async function getProductFunction({ } imagePath } - productVariants(where: $variantId ? { id: { equals: $variantId } } : {}) { + productVariants(where: $variantWhere) { id title sku @@ -260,7 +347,7 @@ export async function getProductFunction({ const { product } = await openFrontClient.request(gqlQuery, { productId, - variantId, + variantWhere: variantId ? { id: { equals: variantId } } : {}, }) as any; if (!product || product.status !== "published") { @@ -306,108 +393,197 @@ export async function createPurchaseFunction({ }) { console.log(`🛒 OpenFront Channel: Creating purchase with ${cartItems.length} items`); console.log(`🚚 OpenFront Channel: Ship to: ${shipping?.firstName} ${shipping?.lastName}`); + console.log(`📦 OpenFront Channel: Full shipping data:`, JSON.stringify(shipping, null, 2)); + console.log(`📦 OpenFront Channel: Platform data:`, JSON.stringify(platform, null, 2)); + console.log(`📦 OpenFront Channel: Cart items:`, JSON.stringify(cartItems, null, 2)); const openFrontClient = await createOpenFrontClient(platform); - // Generate unique purchase ID - const purchaseId = `PO-OF-${Date.now()}`; - const orderNumber = `#${purchaseId}`; - - // Calculate total price - const totalPrice = cartItems.reduce((sum: number, item: any) => { - return sum + (parseFloat(item.price) * item.quantity); - }, 0); - - // Create fulfillment order in OpenFront - const createOrderMutation = gql` - mutation CreateFulfillmentOrder($data: OrderCreateInput!) { - createOrder(data: $data) { - id - orderNumber - total - status - orderLineItems { + try { + // Step 1: Get region data with currency ID and taxRate (like storefront does) + const currencyCode = (shipping?.currency || "USD").toLowerCase(); + const getRegionQuery = gql` + query GetRegion($currencyCode: String!) { + regions(where: { currency: { code: { equals: $currencyCode } } }) { id - title - quantity - unitPrice - productVariant { + taxRate + currency { id - title - sku - product { + code + } + } + } + `; + + const { regions } = await openFrontClient.request(getRegionQuery, { + currencyCode: currencyCode, + }) as any; + + const region = regions[0]; + if (!region) { + throw new Error(`No region found for currency: ${currencyCode}`); + } + + // Step 2: Create cart (following storefront flow) + console.log("🛒 [OpenFront Channel] Creating cart with region:", region.id); + + const { createCart: cart } = await openFrontClient.request(gql` + mutation CreateCart($data: CartCreateInput!) { + createCart(data: $data) { + id + region { + id + currency { id - title + code } } } } - } - `; - - try { - // Prepare order data - const orderData = { - orderNumber, - customerEmail: shipping?.email || "fulfillment@openship.org", - firstName: shipping?.firstName || "Fulfillment", - lastName: shipping?.lastName || "Order", - address1: shipping?.streetAddress1 || "", - address2: shipping?.streetAddress2 || "", - city: shipping?.city || "", - state: shipping?.state || "", - postalCode: shipping?.zip || "", - countryCode: shipping?.country || "US", - phone: shipping?.phone || "", - total: Math.round(totalPrice * 100), // Convert to cents - subtotal: Math.round(totalPrice * 100), - status: "pending_fulfillment", - orderLineItems: { - create: cartItems.map((item: any) => ({ - title: item.name || `Product ${item.variantId}`, - quantity: item.quantity, - unitPrice: Math.round(parseFloat(item.price) * 100), // Convert to cents - productVariant: { connect: { id: item.variantId } } - })) + `, { + data: { + region: { connect: { id: region.id } }, + email: shipping?.email || `order-${Date.now()}@openship.generated` } - }; - - const result = await openFrontClient.request(createOrderMutation, { - data: orderData, }) as any; - const order = result.createOrder; + console.log("✅ [OpenFront Channel] Cart created with ID:", cart.id); - console.log(`📧 OpenFront Channel: Fulfillment Order Created: ${orderNumber}`); - console.log(`💰 OpenFront Channel: Total: $${totalPrice.toFixed(2)}`); + // Step 3: Add line items to cart (this computes unitPrice/total automatically) + const lineItemsToCreate = []; + for (const item of cartItems) { + lineItemsToCreate.push({ + productVariant: { connect: { id: item.variantId } }, + quantity: item.quantity + }); + } - // Process line items for response - const processedLineItems = order.orderLineItems.map((item: any) => ({ - id: item.id, - title: item.title, + console.log("📦 [OpenFront Channel] Adding", lineItemsToCreate.length, "line items to cart"); + + await openFrontClient.request(gql` + mutation AddLineItemsToCart($cartId: ID!, $data: CartUpdateInput!) { + updateActiveCart(cartId: $cartId, data: $data) { + id + } + } + `, { + cartId: cart.id, + data: { + lineItems: { + create: lineItemsToCreate + } + } + }) as any; + + console.log("✅ [OpenFront Channel] Line items added to cart"); + + // Step 4: Create addresses and add to cart + console.log("📍 [OpenFront Channel] Creating shipping address"); + + const { createAddress: shippingAddr } = await openFrontClient.request(gql` + mutation CreateAddress($data: AddressCreateInput!) { + createAddress(data: $data) { + id + } + } + `, { + data: { + firstName: shipping?.firstName || "Guest", + lastName: shipping?.lastName || "Customer", + address1: shipping?.address1 || "123 Default St", + city: shipping?.city || "Default City", + province: shipping?.state || "NY", + postalCode: shipping?.zip || "10001", + phone: shipping?.phone || "", + country: { + connect: { + iso2: (shipping?.country || "US").toLowerCase() + } + } + } + }) as any; + + console.log("✅ [OpenFront Channel] Shipping address created:", shippingAddr.id); + + // Step 5: Update cart with addresses + await openFrontClient.request(gql` + mutation UpdateCartAddresses($cartId: ID!, $data: CartUpdateInput!) { + updateActiveCart(cartId: $cartId, data: $data) { + id + } + } + `, { + cartId: cart.id, + data: { + shippingAddress: { connect: { id: shippingAddr.id } }, + billingAddress: { connect: { id: shippingAddr.id } } + } + }) as any; + + console.log("✅ [OpenFront Channel] Cart updated with addresses"); + + // Step 6: Complete cart to create order (like storefront placeOrder) + console.log("🎯 [OpenFront Channel] Completing cart to create order"); + + console.log("🎯 [OpenFront Channel] Calling completeActiveCart for cart:", cart.id); + + const completeResult = await openFrontClient.request(gql` + mutation CompleteActiveCart($cartId: ID!) { + completeActiveCart(cartId: $cartId) + } + `, { + cartId: cart.id + }) as any; + + console.log("🔍 [OpenFront Channel] completeActiveCart result:", JSON.stringify(completeResult, null, 2)); + + const order = completeResult.completeActiveCart; + if (!order?.id) { + throw new Error("Failed to complete cart - no order created"); + } + + console.log("🔍 [OpenFront Channel] COMPLETE ORDER RESULT:", JSON.stringify(order, null, 2)); + console.log("🎉 [OpenFront Channel] Order created successfully:", order.id); + + // Process line items from cart items (since order doesn't include line items) + const processedLineItems = cartItems.map((item: any) => ({ + id: item.variantId, + title: item.name || `Product ${item.variantId}`, quantity: item.quantity, - variantId: item.productVariant.id, - productId: item.productVariant.product.id + variantId: item.variantId, })); - // Return success response + // Return in the same format as Shopify channel return { purchaseId: order.id, - orderNumber: order.orderNumber, - totalPrice: (order.total / 100).toFixed(2), + orderNumber: `#${order.displayId}`, + totalPrice: order.total, invoiceUrl: `https://${platform.domain}/admin/orders/${order.id}`, lineItems: processedLineItems, - status: "processing" + status: "pending", }; - } catch (error) { - console.error('OpenFront Channel: Purchase creation failed:', error); + } catch (error: any) { + console.error('🚨 OpenFront Channel: Purchase creation failed:', error); - // Return error response + if (error.response?.errors) { + console.error('🚨 GraphQL Errors:'); + error.response.errors.forEach((err: any, i: number) => { + console.error(` ${i + 1}. ${err.message}`); + if (err.path) { + console.error(` Path: ${err.path.join(' -> ')}`); + } + if (err.extensions) { + console.error(` Extensions:`, err.extensions); + } + }); + } + + // Return error response with detailed error info return { - purchaseId, - orderNumber, - totalPrice: totalPrice.toFixed(2), + purchaseId: null, + orderNumber: null, + totalPrice: "0.00", invoiceUrl: null, lineItems: cartItems.map((item: any) => ({ id: `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, @@ -422,7 +598,7 @@ export async function createPurchaseFunction({ } } -// Function to create webhook for channel events +// Function to create webhook for channel events - simplified to update user's webhook URL export async function createWebhookFunction({ platform, endpoint, @@ -432,46 +608,128 @@ export async function createWebhookFunction({ endpoint: string; events: string[]; }) { - const openFrontClient = await createOpenFrontClient(platform); + console.log('🪝 [OpenFront Channel] createWebhookFunction called'); + console.log('🪝 [OpenFront Channel] Platform domain:', platform.domain); + console.log('🪝 [OpenFront Channel] Endpoint URL:', endpoint); + console.log('🪝 [OpenFront Channel] Events received:', events); + console.log('🪝 [OpenFront Channel] Events type:', typeof events, 'Array?', Array.isArray(events)); + console.log('🪝 [OpenFront Channel] Platform data:', JSON.stringify(platform, null, 2)); - const createWebhookMutation = gql` - mutation CreateChannelWebhookEndpoint($data: WebhookEndpointCreateInput!) { - createWebhookEndpoint(data: $data) { - id - url - events - isActive - secret + // Map Openship channel events to OpenFront events + const eventMap: Record = { + ORDER_CREATED: "order.created", + ORDER_CANCELLED: "order.cancelled", + TRACKING_CREATED: "fulfillment.created", + }; + + const openFrontEvents = events.map(event => { + const mapped = eventMap[event] || event; + console.log(`🪝 [OpenFront Channel] Mapping: ${event} -> ${mapped}`); + return mapped; + }); + console.log('🪝 [OpenFront Channel] Final mapped events array:', openFrontEvents); + console.log('🪝 [OpenFront Channel] Joined events string:', openFrontEvents.join(", ")); + + try { + console.log('🪝 [OpenFront Channel] Creating OpenFront GraphQL client...'); + const openFrontClient = await createOpenFrontClient(platform); + console.log('✅ [OpenFront Channel] GraphQL client created successfully'); + + // Get current user from the access token + console.log('🪝 [OpenFront Channel] Fetching current user...'); + const getUserQuery = gql` + query GetCurrentUser { + authenticatedItem { + ... on User { + id + email + orderWebhookUrl + } + } + } + `; + + console.log('🪝 [OpenFront Channel] Executing getUserQuery...'); + const { authenticatedItem: user } = await openFrontClient.request(getUserQuery) as any; + console.log('🪝 [OpenFront Channel] getUserQuery result:', JSON.stringify(user, null, 2)); + + if (!user) { + console.error('🚨 [OpenFront Channel] User not authenticated - authenticatedItem is null/undefined'); + throw new Error('User not authenticated'); + } + + console.log('✅ [OpenFront Channel] User authenticated successfully'); + console.log('🪝 [OpenFront Channel] User ID:', user.id); + console.log('🪝 [OpenFront Channel] User email:', user.email); + console.log('🪝 [OpenFront Channel] Current webhook URL:', user.orderWebhookUrl); + + // Update the user's webhook URL using updateActiveUser (bypasses access restrictions) + console.log('🪝 [OpenFront Channel] Updating user webhook URL...'); + const updateUserMutation = gql` + mutation UpdateActiveUserWebhookUrl($data: UserUpdateProfileInput!) { + updateActiveUser(data: $data) { + id + orderWebhookUrl + } + } + `; + + console.log('🪝 [OpenFront Channel] Update mutation variables:'); + console.log('🪝 [OpenFront Channel] - User ID:', user.id); + console.log('🪝 [OpenFront Channel] - New webhook URL:', endpoint); + + const result = await openFrontClient.request(updateUserMutation, { + data: { orderWebhookUrl: endpoint } + }) as any; + + console.log('🪝 [OpenFront Channel] Update mutation result:', JSON.stringify(result, null, 2)); + + const updatedUser = result.updateActiveUser; + console.log('✅ [OpenFront Channel] User webhook URL updated successfully'); + console.log('🪝 [OpenFront Channel] Updated user ID:', updatedUser.id); + console.log('🪝 [OpenFront Channel] Updated webhook URL:', updatedUser.orderWebhookUrl); + + const webhookResponse = { + webhooks: [{ + id: `user-${updatedUser.id}`, + callbackUrl: updatedUser.orderWebhookUrl, + topic: openFrontEvents.join(", "), // Join array into comma-separated string + format: "JSON", + createdAt: new Date().toISOString() + }], + webhookId: `user-${updatedUser.id}` + }; + + console.log('🪝 [OpenFront Channel] Final webhook response:', JSON.stringify(webhookResponse, null, 2)); + return webhookResponse; + + } catch (error: any) { + console.error('🚨 [OpenFront Channel] createWebhookFunction failed:', error); + console.error('🚨 [OpenFront Channel] Error message:', error.message); + console.error('🚨 [OpenFront Channel] Error stack:', error.stack); + + if (error.response) { + console.error('🚨 [OpenFront Channel] GraphQL response:', JSON.stringify(error.response, null, 2)); + + if (error.response.errors) { + console.error('🚨 [OpenFront Channel] GraphQL errors:'); + error.response.errors.forEach((err: any, i: number) => { + console.error(`🚨 [OpenFront Channel] ${i + 1}. ${err.message}`); + if (err.path) { + console.error(`🚨 [OpenFront Channel] Path: ${err.path.join(' -> ')}`); + } + if (err.extensions) { + console.error(`🚨 [OpenFront Channel] Extensions:`, err.extensions); + } + }); } } - `; - - // Map channel events to OpenFront events - const eventMap: Record = { - PURCHASE_CREATED: "order.created", - PURCHASE_SHIPPED: "fulfillment.shipped", - INVENTORY_UPDATED: "inventory.updated", - }; - - const openFrontEvents = events.map(event => eventMap[event] || event); - - const result = await openFrontClient.request(createWebhookMutation, { - data: { - url: endpoint, - events: openFrontEvents, - isActive: true, - }, - }) as any; - - const webhook = result.createWebhookEndpoint; - - return { - webhooks: [webhook], - webhookId: webhook.id - }; + + throw error; + } } -// Function to delete webhook +// Function to delete webhook - clear user's webhook URL export async function deleteWebhookFunction({ platform, webhookId, @@ -481,22 +739,28 @@ export async function deleteWebhookFunction({ }) { const openFrontClient = await createOpenFrontClient(platform); - const deleteWebhookMutation = gql` - mutation DeleteChannelWebhookEndpoint($where: WebhookEndpointWhereUniqueInput!) { - deleteWebhookEndpoint(where: $where) { + // Extract user ID from webhookId (format: "user-{userId}") + const userId = webhookId.replace('user-', ''); + + // Clear the user's webhook URL + const updateUserMutation = gql` + mutation ClearUserWebhookUrl($where: UserWhereUniqueInput!, $data: UserUpdateInput!) { + updateUser(where: $where, data: $data) { id + orderWebhookUrl } } `; - const result = await openFrontClient.request(deleteWebhookMutation, { - where: { id: webhookId }, + const result = await openFrontClient.request(updateUserMutation, { + where: { id: userId }, + data: { orderWebhookUrl: null } }); return result; } -// Function to get webhooks +// Function to get webhooks - get user's webhook URL export async function getWebhooksFunction({ platform, }: { @@ -504,34 +768,41 @@ export async function getWebhooksFunction({ }) { const openFrontClient = await createOpenFrontClient(platform); - const query = gql` - query GetChannelWebhookEndpoints { - webhookEndpoints(where: { isActive: { equals: true } }) { - id - url - events - isActive - createdAt + // Map OpenFront events back to Openship channel events + const eventMap: Record = { + "order.created": "PURCHASE_CREATED", + "fulfillment.created": "PURCHASE_SHIPPED", + }; + + // Get current user's webhook URL + const getUserQuery = gql` + query GetCurrentUser { + authenticatedItem { + ... on User { + id + email + orderWebhookUrl + createdAt + } } } `; - const { webhookEndpoints } = await openFrontClient.request(query) as any; + const { authenticatedItem: user } = await openFrontClient.request(getUserQuery) as any; + + if (!user || !user.orderWebhookUrl) { + return { webhooks: [] }; + } - // Map OpenFront events back to channel events - const eventMap: Record = { - "order.created": "PURCHASE_CREATED", - "fulfillment.shipped": "PURCHASE_SHIPPED", - "inventory.updated": "INVENTORY_UPDATED", - }; - - const webhooks = webhookEndpoints.map((webhook: any) => ({ - id: webhook.id, - callbackUrl: webhook.url, - topic: webhook.events.map((event: string) => eventMap[event] || event), + // For OpenFront channels, we support both PURCHASE_CREATED and PURCHASE_SHIPPED + // Since we store a single webhook URL on the user, we return both events as supported + const webhooks = [{ + id: `user-${user.id}`, + callbackUrl: user.orderWebhookUrl, + topic: ["PURCHASE_CREATED", "PURCHASE_SHIPPED"], // These are the channel events we support format: "JSON", - createdAt: webhook.createdAt, - })); + createdAt: user.createdAt + }]; return { webhooks }; } @@ -702,9 +973,15 @@ export async function oAuthCallbackFunction({ throw new Error(`Failed to exchange OAuth code for access token: ${response.statusText}`); } - const { access_token } = await response.json(); + const { access_token, refresh_token, expires_in } = await response.json(); - return access_token; // Return just the token, as expected by OpenShip + // Return OAuth response with refresh token support + return { + accessToken: access_token, + refreshToken: refresh_token, + expiresIn: expires_in, + tokenExpiresAt: new Date(Date.now() + (expires_in * 1000)).toISOString() + }; } // Required OAuth scopes for OpenFront channel integration diff --git a/features/integrations/shop/openfront.ts b/features/integrations/shop/openfront.ts index 6eb6dbb..361cab6 100644 --- a/features/integrations/shop/openfront.ts +++ b/features/integrations/shop/openfront.ts @@ -1,5 +1,6 @@ import { GraphQLClient, gql } from "graphql-request"; import { getBaseUrl } from '@/features/dashboard/lib/getBaseUrl'; +import { keystoneContext } from '@/features/keystone/context'; interface OpenFrontPlatform { domain: string; @@ -58,48 +59,132 @@ interface WebhookEventArgs { // Helper function to get fresh access token with proper OAuth 2.0 flow const getFreshAccessToken = async (platform: OpenFrontPlatform) => { - // Check if we have local access token expiry information - if (platform.tokenExpiresAt && platform.refreshToken) { - const expiresAt = typeof platform.tokenExpiresAt === 'string' - ? new Date(platform.tokenExpiresAt) - : platform.tokenExpiresAt; - - // If access token hasn't expired yet, use it - if (expiresAt > new Date()) { - return platform.accessToken; - } - - - // Use refresh token to get new access token - const tokenUrl = `${platform.domain}/api/oauth/token`; - - const formData = new URLSearchParams({ - grant_type: "refresh_token", - refresh_token: platform.refreshToken, - }); - - const response = await fetch(tokenUrl, { - method: "POST", - headers: { "Content-Type": "application/x-www-form-urlencoded" }, - body: formData, - }); - - if (!response.ok) { - const errorText = await response.text(); - console.error('Token refresh failed:', errorText); - throw new Error(`Failed to refresh access token: ${response.statusText} - ${errorText}`); - } - - const { access_token } = await response.json(); - - // TODO: Update stored access token and expiry in database - // This would require updating the shop/channel record with new tokens - - return access_token; + console.log('🔄 [OpenFront Shop] getFreshAccessToken called'); + console.log('🔄 [OpenFront Shop] Platform domain:', platform.domain); + console.log('🔄 [OpenFront Shop] Actual access token:', platform.accessToken); + + // Get shop with OAuth credentials from database + const shops = await keystoneContext.sudo().query.Shop.findMany({ + where: { + domain: { equals: platform.domain }, + accessToken: { equals: platform.accessToken } + }, + query: 'id refreshToken tokenExpiresAt platform { appKey appSecret }' + }); + + if (!shops || shops.length === 0) { + console.log('⚠️ [OpenFront Shop] No matching shop found in database'); + return platform.accessToken; } + const shop = shops[0]; + console.log('🔄 [OpenFront Shop] Found shop:', shop.id); + console.log('🔄 [OpenFront Shop] Has refresh token:', !!shop.refreshToken); + console.log('🔄 [OpenFront Shop] Token expires at:', shop.tokenExpiresAt); + console.log('🔄 [OpenFront Shop] Has appKey:', !!shop.platform?.appKey); + console.log('🔄 [OpenFront Shop] Has appSecret:', !!shop.platform?.appSecret); + console.log('🔄 [OpenFront Shop] Actual refresh token:', shop.refreshToken); - // If no refresh capability, just use the access token as-is + // If we have a refresh token, check if we need to refresh + if (shop.refreshToken) { + console.log('🔄 [OpenFront Shop] Refresh token found, checking if refresh needed'); + + // Check if access token has expired (if we have expiry info) + let shouldRefresh = false; + + if (shop.tokenExpiresAt) { + const expiresAt = typeof shop.tokenExpiresAt === 'string' + ? new Date(shop.tokenExpiresAt) + : shop.tokenExpiresAt; + + const now = new Date(); + shouldRefresh = expiresAt <= now; + + console.log('🔄 [OpenFront Shop] Token expiry check:'); + console.log('🔄 [OpenFront Shop] - Expires at:', expiresAt.toISOString()); + console.log('🔄 [OpenFront Shop] - Current time:', now.toISOString()); + console.log('🔄 [OpenFront Shop] - Should refresh:', shouldRefresh); + } else { + // If no expiry info, assume token needs refresh + shouldRefresh = true; + console.log('🔄 [OpenFront Shop] No expiry info found, assuming refresh needed'); + } + + if (shouldRefresh) { + console.log('🔄 [OpenFront Shop] Starting token refresh process...'); + + // Use refresh token to get new access token + const tokenUrl = `${platform.domain}/api/oauth/token`; + console.log('🔄 [OpenFront Shop] Token URL:', tokenUrl); + + const formData = new URLSearchParams({ + grant_type: "refresh_token", + refresh_token: shop.refreshToken, + client_id: shop.platform?.appKey || "", + client_secret: shop.platform?.appSecret || "", + }); + + console.log('🔄 [OpenFront Shop] Refresh request params:'); + console.log('🔄 [OpenFront Shop] - grant_type: refresh_token'); + console.log('🔄 [OpenFront Shop] - client_id:', shop.platform?.appKey || "NOT_SET"); + console.log('🔄 [OpenFront Shop] - client_secret:', shop.platform?.appSecret ? "SET" : "NOT_SET"); + console.log('🔄 [OpenFront Shop] - refresh_token:', shop.refreshToken ? "SET" : "NOT_SET"); + + console.log('🔄 [OpenFront Shop] Making refresh token request...'); + const response = await fetch(tokenUrl, { + method: "POST", + headers: { "Content-Type": "application/x-www-form-urlencoded" }, + body: formData, + }); + + console.log('🔄 [OpenFront Shop] Refresh response status:', response.status); + console.log('🔄 [OpenFront Shop] Refresh response ok:', response.ok); + + if (!response.ok) { + const errorText = await response.text(); + console.error('🚨 [OpenFront Shop] Token refresh failed:', errorText); + console.error('🚨 [OpenFront Shop] Response status:', response.status); + console.error('🚨 [OpenFront Shop] Response statusText:', response.statusText); + throw new Error(`Failed to refresh access token: ${response.statusText} - ${errorText}`); + } + + const tokenData = await response.json(); + console.log('🔄 [OpenFront Shop] Token refresh response received'); + console.log('🔄 [OpenFront Shop] - Has access_token:', !!tokenData.access_token); + console.log('🔄 [OpenFront Shop] - Has refresh_token:', !!tokenData.refresh_token); + console.log('🔄 [OpenFront Shop] - Expires in:', tokenData.expires_in, 'seconds'); + + const { access_token, refresh_token, expires_in } = tokenData; + + // Update stored access token and expiry in database + console.log('🔄 [OpenFront Shop] Updating tokens in database...'); + try { + console.log('🔄 [OpenFront Shop] Updating shop:', shop.id); + await keystoneContext.sudo().query.Shop.updateOne({ + where: { id: shop.id }, + data: { + accessToken: access_token, + ...(refresh_token && { refreshToken: refresh_token }), + ...(expires_in && { tokenExpiresAt: new Date(Date.now() + (expires_in * 1000)) }) + } + }); + console.log('✅ [OpenFront Shop] Shop updated with new tokens:', shop.id); + } catch (error) { + console.error('🚨 [OpenFront Shop] Failed to update shop tokens in database:', error); + // Continue with the request even if database update fails + } + + console.log('✅ [OpenFront Shop] Returning fresh access token'); + return access_token; + } else { + // Token hasn't expired yet, use existing one + console.log('✅ [OpenFront Shop] Token still valid, using existing access token'); + return platform.accessToken; + } + } + + // If no refresh token, just use the access token as-is + console.log('⚠️ [OpenFront Shop] No refresh token available, using existing access token'); return platform.accessToken; }; @@ -370,6 +455,7 @@ export async function searchOrdersFunction({ searchEntry: string; after?: string; }) { + console.log("fuckkk") const openFrontClient = await createOpenFrontClient(platform); const gqlQuery = gql` @@ -459,6 +545,8 @@ export async function searchOrdersFunction({ skip, }) as any; + console.log("Orders from OpenFront:", orders); + // Transform orders to Openship format const transformedOrders = orders.map((order: any) => { const shippingAddress = order.shippingAddress || {}; @@ -481,16 +569,23 @@ export async function searchOrdersFunction({ financialStatus: order.status, totalPrice: order.rawTotal ? (order.rawTotal / 100).toFixed(2) : "0.00", currency: order.currency?.code || "USD", - lineItems: (order.lineItems || []).map((lineItem: any) => ({ - lineItemId: lineItem.id, - name: lineItem.title, - quantity: lineItem.quantity, - image: getProductImageUrl({ imagePath: lineItem.thumbnail, image: { url: lineItem.productVariant?.product?.thumbnail } }, platform.domain) || "", - price: lineItem.moneyAmount ? (lineItem.moneyAmount.amount / 100).toFixed(2) : "0.00", - variantId: lineItem.productVariant?.id || "", - productId: lineItem.productVariant?.product?.id || "", - sku: lineItem.sku || lineItem.productVariant?.sku || "", - })), + lineItems: (order.lineItems || []).map((lineItem: any) => { + // Combine product title and variant title like in channel search + const productTitle = lineItem.productVariant?.product?.title || ''; + const variantTitle = lineItem.productVariant?.title || ''; + const combinedTitle = productTitle && variantTitle ? `${productTitle} - ${variantTitle}` : lineItem.title; + + return { + lineItemId: lineItem.id, + name: combinedTitle, + quantity: lineItem.quantity, + image: getProductImageUrl({ imagePath: lineItem.thumbnail, image: { url: lineItem.productVariant?.product?.thumbnail } }, platform.domain) || "", + price: lineItem.moneyAmount ? (lineItem.moneyAmount.amount / 100).toFixed(2) : "0.00", + variantId: lineItem.productVariant?.id || "", + productId: lineItem.productVariant?.product?.id || "", + sku: lineItem.sku || lineItem.productVariant?.sku || "", + }; + }), cartItems: [], fulfillments: [], note: "", @@ -498,6 +593,8 @@ export async function searchOrdersFunction({ }; }); + console.log("Transformed orders:", transformedOrders); + const hasNextPage = skip + take < ordersCount; const endCursor = hasNextPage ? Buffer.from((skip + take).toString()).toString('base64') : null; @@ -750,12 +847,12 @@ export async function oAuthCallbackFunction({ const { access_token, refresh_token, expires_in } = await response.json(); - // Return OAuth token data for proper storage + // Return OAuth response with refresh token support return { - access_token, - refresh_token, - expires_in, - expires_at: new Date(Date.now() + (expires_in * 1000)) + accessToken: access_token, + refreshToken: refresh_token, + expiresIn: expires_in, + tokenExpiresAt: new Date(Date.now() + (expires_in * 1000)).toISOString() }; } @@ -776,16 +873,23 @@ export async function createOrderWebhookHandler({ } // Transform OpenFront order to Openship format - const lineItemsOutput = event.data?.lineItems?.map((item: any) => ({ - name: item.title, - image: getProductImageUrl(item.productVariant?.product?.productImages?.[0], platform.domain) || item.thumbnail, - price: item.moneyAmount?.amount ? (item.moneyAmount.amount / 100) : 0, // Convert from cents to float - quantity: item.quantity || 0, - productId: item.productVariant?.product?.id?.toString(), - variantId: item.productVariant?.id?.toString(), - sku: item.productVariant?.sku || item.sku || "", - lineItemId: item.id?.toString(), - })) || []; + const lineItemsOutput = event.data?.lineItems?.map((item: any) => { + // Combine product title and variant title like in channel search + const productTitle = item.productVariant?.product?.title || ''; + const variantTitle = item.productVariant?.title || ''; + const combinedTitle = productTitle && variantTitle ? `${productTitle} - ${variantTitle}` : item.title; + + return { + name: combinedTitle, + image: getProductImageUrl(item.productVariant?.product?.productImages?.[0], platform.domain) || item.thumbnail, + price: item.moneyAmount?.amount ? (item.moneyAmount.amount / 100) : 0, // Convert from cents to float + quantity: item.quantity || 0, + productId: item.productVariant?.product?.id?.toString(), + variantId: item.productVariant?.id?.toString(), + sku: item.productVariant?.sku || item.sku || "", + lineItemId: item.id?.toString(), + }; + }) || []; // Return Keystone-ready order data const orderData = event.data; diff --git a/features/keystone/index.ts b/features/keystone/index.ts index 4754eba..73bd381 100644 --- a/features/keystone/index.ts +++ b/features/keystone/index.ts @@ -52,7 +52,6 @@ export function statelessSessions({ // Check for OAuth Bearer token authentication const authHeader = context.req.headers.authorization; - console.log('🔑 AUTH HEADER:', authHeader); if (authHeader?.startsWith("Bearer ")) { const accessToken = authHeader.replace("Bearer ", ""); diff --git a/features/keystone/lib/placeMultipleOrders.ts b/features/keystone/lib/placeMultipleOrders.ts index 4cf154d..bcf732b 100644 --- a/features/keystone/lib/placeMultipleOrders.ts +++ b/features/keystone/lib/placeMultipleOrders.ts @@ -44,6 +44,7 @@ export async function placeMultipleOrders({ ids, query }: { ids: string[]; query zip, country, phone, + currency, user, shop, orderId: shopOrderId, @@ -61,7 +62,8 @@ export async function placeMultipleOrders({ ids, query }: { ids: string[]; query state, zip, country, - phone + phone, + currency shop { domain accessToken @@ -155,6 +157,7 @@ export async function placeMultipleOrders({ ids, query }: { ids: string[]; query country, phone, email: user.email, + currency, }, notes: "", }); diff --git a/features/keystone/models/ChannelPlatform.ts b/features/keystone/models/ChannelPlatform.ts index fdb452b..9515f69 100644 --- a/features/keystone/models/ChannelPlatform.ts +++ b/features/keystone/models/ChannelPlatform.ts @@ -24,8 +24,8 @@ export const ChannelPlatform = list({ description: "Adding these fields will enable this platform to be installed as an app by users.", fields: { - appKey: text({ validation: { isRequired: true } }), - appSecret: text({ validation: { isRequired: true } }), + appKey: text(), + appSecret: text(), callbackUrl: virtual({ field: graphql.field({ type: graphql.String, diff --git a/features/keystone/models/ShopPlatform.ts b/features/keystone/models/ShopPlatform.ts index c224187..8c1273b 100644 --- a/features/keystone/models/ShopPlatform.ts +++ b/features/keystone/models/ShopPlatform.ts @@ -24,8 +24,8 @@ export const ShopPlatform = list({ description: "Adding these fields will enable this platform to be installed as an app by users", fields: { - appKey: text({ validation: { isRequired: true } }), - appSecret: text({ validation: { isRequired: true } }), + appKey: text(), + appSecret: text(), callbackUrl: virtual({ field: graphql.field({ type: graphql.String, diff --git a/features/platform/api-keys/components/CreateApiKey.tsx b/features/platform/api-keys/components/CreateApiKey.tsx index a65cbd8..f189417 100644 --- a/features/platform/api-keys/components/CreateApiKey.tsx +++ b/features/platform/api-keys/components/CreateApiKey.tsx @@ -1,6 +1,7 @@ "use client"; -import { useState } from "react"; +import { useState, useRef, useEffect, useCallback } from "react"; +import { cn } from "@/lib/utils"; import { Button } from "@/components/ui/button"; import { Plus, Copy } from "lucide-react"; import { @@ -15,7 +16,9 @@ import { import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; -import MultipleSelector, { Option } from "@/components/ui/multiselect"; +import { Command, CommandEmpty, CommandGroup, CommandItem, CommandList } from "@/components/ui/command"; +import { XIcon, ChevronDown } from "lucide-react"; +import { DateTimePicker } from "@/components/ui/datetime-picker"; import { createApiKey } from "../actions/getApiKeys"; import { useRouter } from "next/navigation"; import { toast } from "sonner"; @@ -37,7 +40,12 @@ function generateApiKeyToken(): string { return prefix + result; } -// Define API key scopes as options for MultipleSelector +export interface Option { + value: string; + label: string; +} + +// Define API key scopes as options const scopeOptions: Option[] = [ { value: "read_orders", label: "read_orders" }, { value: "write_orders", label: "write_orders" }, @@ -60,6 +68,169 @@ const scopeOptions: Option[] = [ { value: "write_users", label: "write_users" }, ]; +function ScopesMultiSelect({ + value = [], + onChange, + options = [], + placeholder = "Select scopes for this API key", + isDisabled = false, +}: { + value?: Option[]; + onChange?: (options: Option[]) => void; + options?: Option[]; + placeholder?: string; + isDisabled?: boolean; +}) { + const [open, setOpen] = useState(false); + const [inputValue, setInputValue] = useState(""); + const inputRef = useRef(null); + const commandRef = useRef(null); + + // Handle click outside to close dropdown + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if ( + commandRef.current && + !commandRef.current.contains(event.target as Node) + ) { + setOpen(false); + } + }; + + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, []); + + const handleSelect = useCallback( + (option: Option) => { + if (!value.some((v) => v.value === option.value)) { + const newValue = [...value, option]; + onChange?.(newValue); + } + setInputValue(""); + }, + [value, onChange] + ); + + const handleRemove = useCallback( + (optionToRemove: Option) => { + const newValue = value.filter((v) => v.value !== optionToRemove.value); + onChange?.(newValue); + }, + [value, onChange] + ); + + const handleClearAll = useCallback(() => { + onChange?.([]); + }, [onChange]); + + // Filter out selected options and by input value + const filteredOptions = options.filter( + (option) => !value.some((v) => v.value === option.value) && + option.label.toLowerCase().includes(inputValue.toLowerCase()) + ); + + return ( +
+
{ + if (!isDisabled) { + setOpen(true); + inputRef.current?.focus(); + } + }} + > +
+ {value.map((option) => ( +
+ {option.label} + {!isDisabled && ( + + )} +
+ ))} + setInputValue(e.target.value)} + className={cn( + "placeholder:text-muted-foreground flex-1 bg-transparent outline-none", + value.length === 0 ? "w-full" : "w-20" + )} + placeholder={value.length === 0 ? placeholder : ""} + /> +
+
+ {value.length > 0 && !isDisabled && ( + + )} + +
+
+ {open && ( +
+ + + <> + {filteredOptions.length === 0 ? ( + + {inputValue.length > 0 ? ( + <>No results found for "{inputValue}" + ) : ( + <>All options have been selected + )} + + ) : ( + + {filteredOptions.map((option) => ( +
+
handleSelect(option)} + className="relative cursor-pointer rounded-sm px-2 py-2 text-sm outline-none hover:bg-accent hover:text-accent-foreground" + > +
+ {option.label} +
+
+
+ ))} +
+ )} + +
+
+
+ )} +
+ ); +} + export function CreateApiKey() { const [open, setOpen] = useState(false); const [loading, setLoading] = useState(false); @@ -136,10 +307,62 @@ export function CreateApiKey() { const copyToClipboard = async () => { try { - await navigator.clipboard.writeText(createdToken); - toast.success("API key copied to clipboard!"); + // Modern browsers with clipboard API support + if (navigator.clipboard && window.isSecureContext) { + await navigator.clipboard.writeText(createdToken); + toast.success("API key copied to clipboard!"); + return; + } + + // Fallback for older browsers or non-secure contexts + const textArea = document.createElement("textarea"); + textArea.value = createdToken; + textArea.style.position = "fixed"; + textArea.style.left = "-999999px"; + textArea.style.top = "-999999px"; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + + const successful = document.execCommand('copy'); + document.body.removeChild(textArea); + + if (successful) { + toast.success("API key copied to clipboard!"); + } else { + throw new Error("Copy command failed"); + } } catch (error) { - toast.error("Failed to copy API key"); + console.error("Copy failed:", error); + + // Final fallback - detect mobile and provide instructions + const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent); + + if (isMobile) { + // Mobile-specific fallback: create a temporary input and select it + try { + const input = document.createElement("input"); + input.value = createdToken; + input.style.position = "fixed"; + input.style.left = "-999999px"; + input.style.top = "-999999px"; + document.body.appendChild(input); + input.focus(); + input.setSelectionRange(0, input.value.length); + + // Show instructions to user + toast.error("Please manually copy the selected text above"); + + // Clean up after a delay + setTimeout(() => { + document.body.removeChild(input); + }, 5000); + } catch (mobileError) { + toast.error("Copy failed. Please manually select and copy the API key"); + } + } else { + toast.error("Copy failed. Please manually select and copy the API key"); + } } }; @@ -194,18 +417,11 @@ export function CreateApiKey() { - No scopes found

} + options={scopeOptions} onChange={handleScopeChange} - className="text-base" + placeholder="Select scopes for this API key" />

Select the minimum permissions needed for this API key @@ -214,11 +430,10 @@ export function CreateApiKey() {

- setFormData(prev => ({ ...prev, expiresAt: e.target.value }))} + onChange={(value) => setFormData(prev => ({ ...prev, expiresAt: value }))} + placeholder="Set expiration date and time" />
@@ -251,7 +466,7 @@ export function CreateApiKey() {
-
+
{createdToken}
diff --git a/features/platform/channels/components/CreateChannelFromURL.tsx b/features/platform/channels/components/CreateChannelFromURL.tsx index 0ef306e..c0491e4 100644 --- a/features/platform/channels/components/CreateChannelFromURL.tsx +++ b/features/platform/channels/components/CreateChannelFromURL.tsx @@ -59,7 +59,10 @@ export function CreateChannelFromURL({ onChannelCreated, searchParams }: CreateC const [tokenExpiresAt, setTokenExpiresAt] = useState(''); useEffect(() => { - if (!searchParams || !searchParams.showCreateChannel) return; + + if (!searchParams || !searchParams.showCreateChannel) { + return; + } const { platform: urlPlatform, @@ -74,55 +77,58 @@ export function CreateChannelFromURL({ onChannelCreated, searchParams }: CreateC tokenExpiresAt: urlTokenExpiresAt } = searchParams; - if (!urlDomain) return; - console.log('CreateChannelFromURL - Processing OAuth callback:', { - hasClientId: !!client_id, - hasPlatformId: !!urlPlatform, - hasAccessToken: !!urlAccessToken, - hasCode: !!code, - domain: urlDomain - }); + if (!urlDomain) { + return; + } // Auto-generate channel name from domain const domainWithoutProtocol = decodeURIComponent(urlDomain).replace(/^https?:\/\//, ''); const cleanName = domainWithoutProtocol.split('.')[0].replace(/[-_]/g, ' '); - const capitalizedName = cleanName.charAt(0).toUpperCase() + cleanName.slice(1) + ' Channel'; + // Fix OpenFront capitalization specifically + const fixedName = cleanName.replace(/openfront/gi, 'Openfront'); + const capitalizedName = fixedName.charAt(0).toUpperCase() + fixedName.slice(1) + ' Channel'; setName(capitalizedName); setDomain(decodeURIComponent(urlDomain)); // Check if this is marketplace flow (has client_id) or long flow (has platform) - if (client_id && client_secret && app_name && adapter_slug && urlAccessToken) { - // Marketplace flow - OAuth already exchanged, ready to create platform/shop - console.log('✅ Marketplace flow detected'); + if (client_id && client_secret && app_name && adapter_slug && urlAccessToken && urlAccessToken !== 'undefined') { + // Marketplace flow - OAuth already exchanged, ready to create platform/channel + setIsMarketplaceFlow(true); setClientId(client_id); setClientSecret(client_secret); setAppName(app_name); setAdapterSlug(adapter_slug); setAccessToken(urlAccessToken); + + if (urlRefreshToken) { + setRefreshToken(urlRefreshToken); + } + if (urlTokenExpiresAt) { + setTokenExpiresAt(urlTokenExpiresAt); + } } else if (urlPlatform && urlAccessToken) { // Long flow - platform exists, just need to create channel - console.log('✅ Long flow detected'); + setPlatformId(urlPlatform); setAccessToken(urlAccessToken); // Set additional token data if provided - if (urlRefreshToken) setRefreshToken(urlRefreshToken); - if (urlTokenExpiresAt) setTokenExpiresAt(urlTokenExpiresAt); + if (urlRefreshToken) { + setRefreshToken(urlRefreshToken); + } + if (urlTokenExpiresAt) { + setTokenExpiresAt(urlTokenExpiresAt); + } } else { - console.log('❌ Invalid OAuth callback - missing required parameters'); return; } setIsDialogOpen(true); - // Clean URL params - const newUrl = new URL(window.location.href); - ['showCreateChannel', 'platform', 'accessToken', 'domain', 'client_id', 'client_secret', 'app_name', 'adapter_slug', 'refreshToken', 'tokenExpiresAt', 'code'].forEach(param => { - newUrl.searchParams.delete(param); - }); - router.replace(newUrl.pathname + newUrl.search); + // DON'T clean URL params immediately - wait for user action + // This was causing the dialog to lose its data source }, [searchParams, router]); const handleChannelCreation = async () => { @@ -143,20 +149,16 @@ export function CreateChannelFromURL({ onChannelCreated, searchParams }: CreateC // Marketplace flow: Check if platform exists if (isMarketplaceFlow && clientId && clientSecret) { - console.log('🔍 Checking if platform exists for client_id:', clientId); const { getChannelPlatformByClientId } = await import('../actions/getChannelPlatformByClientId'); const platformResult = await getChannelPlatformByClientId(clientId); - console.log('🔍 Platform check result:', platformResult); if (platformResult.success && platformResult.data) { // Platform exists, use it finalPlatformId = platformResult.data.id; - console.log('✅ Found existing platform ID:', finalPlatformId, 'Name:', platformResult.data.name); } else { // Platform doesn't exist, will create inline with shop - console.log('📦 Platform does not exist, will create inline'); finalPlatformId = null; } } @@ -168,27 +170,27 @@ export function CreateChannelFromURL({ onChannelCreated, searchParams }: CreateC return; } - // Create the shop + // Create the channel const channelData: any = { name: name.trim(), domain: domain.trim(), accessToken: finalAccessToken.trim(), - ...(refreshToken && { refreshToken: refreshToken }), - ...(tokenExpiresAt && { tokenExpiresAt: new Date(tokenExpiresAt) }), }; - console.log('🏪 Creating channel with data:'); - console.log(' - finalPlatformId:', finalPlatformId); - console.log(' - isMarketplaceFlow:', isMarketplaceFlow); - console.log(' - clientId:', clientId); - console.log(' - adapterSlug:', adapterSlug); + + if (refreshToken) { + channelData.refreshToken = refreshToken; + } + + if (tokenExpiresAt) { + channelData.tokenExpiresAt = new Date(tokenExpiresAt); + } + if (finalPlatformId) { - console.log('🔗 Using existing platform ID:', finalPlatformId); channelData.platformId = finalPlatformId; } else if (isMarketplaceFlow && clientId && clientSecret && appName && adapterSlug) { // Create platform inline using dynamic adapter slug - console.log('📦 Creating platform inline with adapter:', adapterSlug); channelData.platform = { create: { name: appName + ' (Auto-created)', @@ -207,19 +209,22 @@ export function CreateChannelFromURL({ onChannelCreated, searchParams }: CreateC deleteWebhookFunction: adapterSlug, } }; - console.log('📦 Platform inline creation data:', channelData.platform.create); - } else { - console.log('❌ No platform connection - this will cause an error'); - console.log('❌ Missing: finalPlatformId?', !finalPlatformId, 'isMarketplaceFlow?', !isMarketplaceFlow, 'clientId?', !clientId, 'adapterSlug?', !adapterSlug); } - console.log('🏪 Final channelData before createChannel call:', JSON.stringify(channelData, null, 2)); const channelResult = await createChannel(channelData); if (channelResult.success) { toast.success('Channel connected successfully!'); setIsDialogOpen(false); + + // Clean URL params after successful creation + const newUrl = new URL(window.location.href); + ['showCreateChannel', 'platform', 'accessToken', 'domain', 'client_id', 'client_secret', 'app_name', 'adapter_slug', 'refreshToken', 'tokenExpiresAt', 'code'].forEach(param => { + newUrl.searchParams.delete(param); + }); + router.replace(newUrl.pathname + newUrl.search); + router.refresh(); if (onChannelCreated) { @@ -229,7 +234,6 @@ export function CreateChannelFromURL({ onChannelCreated, searchParams }: CreateC toast.error(channelResult.error || 'Failed to create channel'); } } catch (error) { - console.error('Error creating channel:', error); toast.error(error instanceof Error ? error.message : 'Failed to create channel'); } finally { setIsLoading(false); @@ -255,10 +259,10 @@ export function CreateChannelFromURL({ onChannelCreated, searchParams }: CreateC - Connect OpenFront Channel + Connect Openfront Channel {isMarketplaceFlow - ? 'Setting up your OpenFront integration. We\'ll create the platform if needed and connect your channel.' + ? 'Setting up your Openfront integration. We\'ll create the platform if needed and connect your channel.' : 'Complete your channel setup with the OAuth credentials received.' } @@ -304,7 +308,7 @@ export function CreateChannelFromURL({ onChannelCreated, searchParams }: CreateC {isMarketplaceFlow && (

- OpenFront Integration + Openfront Integration

This platform will be created with the channel. diff --git a/features/platform/components/PlatformTabs.tsx b/features/platform/components/PlatformTabs.tsx index 32d23db..c3a4493 100644 --- a/features/platform/components/PlatformTabs.tsx +++ b/features/platform/components/PlatformTabs.tsx @@ -131,12 +131,9 @@ export function PlatformTabs({ >

{platform.name} - + {platform.count || 0} - + {(renderEditButton || onEditPlatform) && ( renderEditButton ? renderEditButton(platform) : (
); diff --git a/features/platform/matches/components/StatusTabs.tsx b/features/platform/matches/components/StatusTabs.tsx index 3a8deeb..20c1bdf 100644 --- a/features/platform/matches/components/StatusTabs.tsx +++ b/features/platform/matches/components/StatusTabs.tsx @@ -9,17 +9,18 @@ import { Checkbox } from "@/components/ui/checkbox"; const statusConfig = { SHOP: { label: "Shop Products", - icon: Layers3, + // No icon for platforms color: "blue" }, CHANNEL: { label: "Channel Products", - icon: Database, + // No icon for platforms color: "green" }, MATCHES: { label: "Matches", icon: Square, + iconColor: "text-purple-500", color: "purple" }, } as const; @@ -90,13 +91,14 @@ export function StatusTabs({ statusCounts, onSelectAll, selectedItems, totalItem updateScroll(n => n + 1); }; - const activeIndex = statuses.findIndex((s) => s.value === currentStatus); + const activeIndex = currentStatus === "all" ? 0 : statuses.findIndex((s) => s.value === currentStatus) + 1; const activeTabOffsetLeft = tabRefs.current[activeIndex]?.offsetLeft || 0; const activeTabWidth = tabRefs.current[activeIndex]?.offsetWidth || 0; const scrollOffset = scrollContainerRef.current ? scrollContainerRef.current.scrollLeft : 0; return (
+ {/* Hover background */}
+ {/* Active indicator line */}
@@ -124,25 +128,32 @@ export function StatusTabs({ statusCounts, onSelectAll, selectedItems, totalItem /> )} {statuses.map((status, index) => { - const StatusIcon = statusConfig[status.value as keyof typeof statusConfig].icon; + const config = statusConfig[status.value as keyof typeof statusConfig]; + const StatusIcon = config.icon; + const iconColor = config.iconColor; + const isActive = currentStatus === status.value; + return (
{ tabRefs.current[index] = el }} + ref={el => { tabRefs.current[index + 1] = el }} className={`px-3 py-2 cursor-pointer transition-colors duration-300 ${ - currentStatus === status.value + isActive ? "text-foreground" : "text-muted-foreground" }`} - onMouseEnter={() => setHoveredIndex(index)} + onMouseEnter={() => setHoveredIndex(index + 1)} onMouseLeave={() => setHoveredIndex(null)} onClick={() => handleStatusChange(status.value)} >
+ {/* Only show icon for MATCHES */} + {StatusIcon && } {status.label} - + {/* Use neutral badge for all tabs */} + {status.count} - +
); diff --git a/features/platform/orders/components/ChannelSearchAccordion.tsx b/features/platform/orders/components/ChannelSearchAccordion.tsx index ce59c30..3e69286 100644 --- a/features/platform/orders/components/ChannelSearchAccordion.tsx +++ b/features/platform/orders/components/ChannelSearchAccordion.tsx @@ -164,7 +164,7 @@ export const ChannelSearchAccordion: React.FC = ({
{searchResults.map((product) => (
diff --git a/features/platform/orders/components/OrderDetailsComponent.tsx b/features/platform/orders/components/OrderDetailsComponent.tsx index 61a5f22..c5d296d 100644 --- a/features/platform/orders/components/OrderDetailsComponent.tsx +++ b/features/platform/orders/components/OrderDetailsComponent.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { useState } from "react"; +import React, { useState, useCallback } from "react"; // Helper function to safely format price - handles text prices that may not be numeric function formatPrice(price: string | number | undefined, currency: string = '$'): string { @@ -78,6 +78,18 @@ import { useToast } from '@/components/ui/use-toast'; import { Order } from "../lib/types"; import { Checkbox } from "@/components/ui/checkbox"; import { Badge } from "@/components/ui/badge"; +import { deleteItemAction } from '@/features/dashboard/actions/item-actions'; +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger +} from '@/components/ui/alert-dialog'; interface OrderDetailsComponentProps { order: Order; @@ -133,6 +145,37 @@ export const OrderDetailsComponent = ({ onAction('matchOrder', order.id); }; + // Delete handler exactly like EditItemDrawer + const handleDelete = useCallback(async () => { + try { + const { errors } = await deleteItemAction('Order', order.id); + + const error = errors?.find(x => x.path === undefined || x.path?.length === 1); + if (error) { + toast({ + title: 'Unable to delete order', + description: error.message, + variant: 'destructive' + }); + return; + } + + toast({ + title: 'Order deleted successfully' + }); + + // Refresh the page or trigger parent refresh + window.location.reload(); + + } catch (err: any) { + toast({ + title: 'Unable to delete order', + description: err.message || "An unexpected error occurred", + variant: 'destructive' + }); + } + }, [order.id, toast]); + return ( <> @@ -197,7 +240,8 @@ export const OrderDetailsComponent = ({ {currentAction && ( {getLoadingText(currentAction)} @@ -214,54 +258,52 @@ export const OrderDetailsComponent = ({ - + onAction("getMatch", order.id)}> - onAction("saveMatch", order.id)}> - onAction("placeOrder", order.id)}> - setIsEditDrawerOpen(true)}> - - { - if (confirm(`Are you sure you want to delete order ${order.orderName || order.orderId}? This action cannot be undone.`)) { - onAction("deleteOrder", order.id); - } - }} - className="text-red-600 focus:text-red-600 focus:bg-red-50 dark:focus:bg-red-950/50" - > - + + + e.preventDefault()} + className="text-red-600 focus:text-red-600 focus:bg-red-50 dark:focus:bg-red-950/50" + > + + + + + Delete order + + Are you sure you want to delete{' '} + + Order {order.orderName || `#${order.orderId}`} + + ? This action cannot be undone. + + + + Cancel + + Yes, delete + + + + )} diff --git a/features/platform/orders/components/StatusBadge.tsx b/features/platform/orders/components/StatusBadge.tsx index b88ec99..9b8e101 100644 --- a/features/platform/orders/components/StatusBadge.tsx +++ b/features/platform/orders/components/StatusBadge.tsx @@ -34,7 +34,6 @@ interface StatusBadgeProps { export function StatusBadge({ status }: StatusBadgeProps) { return ( {status} diff --git a/features/platform/shops/actions/createShop.ts b/features/platform/shops/actions/createShop.ts index 0bde28c..fe4b72b 100644 --- a/features/platform/shops/actions/createShop.ts +++ b/features/platform/shops/actions/createShop.ts @@ -17,12 +17,26 @@ export interface CreateShopInput { } export async function createShop(data: CreateShopInput) { + console.log('🏪 createShop action called with data:'); + console.log(' - name:', data.name); + console.log(' - domain:', data.domain); + console.log(' - accessToken present:', !!data.accessToken); + console.log(' - refreshToken present:', !!data.refreshToken); + console.log(' - refreshToken value:', data.refreshToken ? `${data.refreshToken.substring(0, 10)}...` : 'MISSING'); + console.log(' - tokenExpiresAt present:', !!data.tokenExpiresAt); + console.log(' - tokenExpiresAt value:', data.tokenExpiresAt); + console.log(' - platformId:', data.platformId); + console.log(' - platform.create present:', !!data.platform?.create); + const mutation = ` mutation CreateShop($data: ShopCreateInput!) { createShop(data: $data) { id name domain + accessToken + refreshToken + tokenExpiresAt platform { id name @@ -35,31 +49,76 @@ export async function createShop(data: CreateShopInput) { let platformData; if (data.platformId) { // Existing platform - connect by ID + console.log('🔗 Using existing platform ID:', data.platformId); platformData = { connect: { id: data.platformId } }; } else if (data.platform?.create) { // Inline platform creation + console.log('📦 Creating platform inline:', data.platform.create); platformData = { create: data.platform.create }; } else { + console.log('❌ No platform connection method provided'); throw new Error('Either platformId or platform.create must be provided'); } - const variables = { + const variables: { + data: { + name: string; + domain: string; + accessToken: string; + refreshToken?: string; + tokenExpiresAt?: string; + platform?: any; + } + } = { data: { name: data.name, domain: data.domain, accessToken: data.accessToken, - ...(data.refreshToken && { refreshToken: data.refreshToken }), - ...(data.tokenExpiresAt && { tokenExpiresAt: data.tokenExpiresAt.toISOString() }), - platform: platformData } }; + console.log('🔍 Building GraphQL variables:'); + console.log(' - Base variables:', JSON.stringify(variables, null, 2)); + + if (data.refreshToken) { + console.log('🔑 Adding refreshToken to variables:', data.refreshToken ? `${data.refreshToken.substring(0, 10)}...` : 'MISSING'); + variables.data.refreshToken = data.refreshToken; + } else { + console.log('❌ No refreshToken to add'); + } + + if (data.tokenExpiresAt) { + console.log('⏰ Adding tokenExpiresAt to variables:', data.tokenExpiresAt); + variables.data.tokenExpiresAt = data.tokenExpiresAt.toISOString(); + } else { + console.log('❌ No tokenExpiresAt to add'); + } + + variables.data.platform = platformData; + + console.log('🚀 Final GraphQL variables being sent:'); + console.log(JSON.stringify(variables, null, 2)); + const response = await keystoneClient(mutation, variables); - console.log('Created shop response:', response); + console.log('📨 GraphQL response received:'); + console.log(' - success:', response.success); + console.log(' - data:', JSON.stringify(response.data, null, 2)); + console.log(' - error:', response.error); if (response.success && response.data?.createShop) { + console.log('✅ Shop created successfully:'); + console.log(' - ID:', response.data.createShop.id); + console.log(' - Name:', response.data.createShop.name); + console.log(' - Domain:', response.data.createShop.domain); + console.log(' - Has accessToken:', !!response.data.createShop.accessToken); + console.log(' - Has refreshToken:', !!response.data.createShop.refreshToken); + console.log(' - TokenExpiresAt:', response.data.createShop.tokenExpiresAt); return { success: true, shop: response.data.createShop }; } else { + console.log('❌ Shop creation failed:'); + console.log(' - Response success:', response.success); + console.log(' - Response error:', response.error); + console.log(' - Full response:', JSON.stringify(response, null, 2)); return { success: false, error: response.error || 'Failed to create shop' diff --git a/features/platform/shops/components/CreateShopFromURL.tsx b/features/platform/shops/components/CreateShopFromURL.tsx index 9a03442..99bd595 100644 --- a/features/platform/shops/components/CreateShopFromURL.tsx +++ b/features/platform/shops/components/CreateShopFromURL.tsx @@ -3,7 +3,7 @@ import React, { useState, useEffect } from "react"; import { useRouter } from "next/navigation"; import { Button } from "@/components/ui/button"; -import { createShop } from "../actions/createShop"; +import { createShop, CreateShopInput } from "../actions/createShop"; import { createShopPlatform } from "../actions/createShopPlatform"; import { toast } from "sonner"; import { @@ -76,14 +76,6 @@ export function CreateShopFromURL({ onShopCreated, searchParams }: CreateShopFro if (!urlDomain) return; - console.log('CreateShopFromURL - Processing OAuth callback:', { - hasClientId: !!client_id, - hasPlatformId: !!urlPlatform, - hasAccessToken: !!urlAccessToken, - hasCode: !!code, - domain: urlDomain - }); - // Auto-generate shop name from domain const domainWithoutProtocol = decodeURIComponent(urlDomain).replace(/^https?:\/\//, ''); const cleanName = domainWithoutProtocol.split('.')[0].replace(/[-_]/g, ' '); @@ -92,37 +84,38 @@ export function CreateShopFromURL({ onShopCreated, searchParams }: CreateShopFro setDomain(decodeURIComponent(urlDomain)); // Check if this is marketplace flow (has client_id) or long flow (has platform) - if (client_id && client_secret && app_name && adapter_slug && urlAccessToken) { + if (client_id && client_secret && app_name && adapter_slug && urlAccessToken && urlAccessToken !== 'undefined') { // Marketplace flow - OAuth already exchanged, ready to create platform/shop - console.log('✅ Marketplace flow detected'); setIsMarketplaceFlow(true); setClientId(client_id); setClientSecret(client_secret); setAppName(app_name); setAdapterSlug(adapter_slug); setAccessToken(urlAccessToken); + + if (urlRefreshToken) { + setRefreshToken(urlRefreshToken); + } + if (urlTokenExpiresAt) { + setTokenExpiresAt(urlTokenExpiresAt); + } } else if (urlPlatform && urlAccessToken) { // Long flow - platform exists, just need to create shop - console.log('✅ Long flow detected'); setPlatformId(urlPlatform); setAccessToken(urlAccessToken); // Set additional token data if provided - if (urlRefreshToken) setRefreshToken(urlRefreshToken); - if (urlTokenExpiresAt) setTokenExpiresAt(urlTokenExpiresAt); + if (urlRefreshToken) { + setRefreshToken(urlRefreshToken); + } + if (urlTokenExpiresAt) { + setTokenExpiresAt(urlTokenExpiresAt); + } } else { - console.log('❌ Invalid OAuth callback - missing required parameters'); return; } setIsDialogOpen(true); - - // Clean URL params - const newUrl = new URL(window.location.href); - ['showCreateShop', 'platform', 'accessToken', 'domain', 'client_id', 'client_secret', 'app_name', 'adapter_slug', 'refreshToken', 'tokenExpiresAt', 'code'].forEach(param => { - newUrl.searchParams.delete(param); - }); - router.replace(newUrl.pathname + newUrl.search); }, [searchParams, router]); const handleShopCreation = async () => { @@ -143,20 +136,14 @@ export function CreateShopFromURL({ onShopCreated, searchParams }: CreateShopFro // Marketplace flow: Check if platform exists if (isMarketplaceFlow && clientId && clientSecret) { - console.log('🔍 Checking if platform exists for client_id:', clientId); - const { getShopPlatformByClientId } = await import('../actions/getShopPlatformByClientId'); const platformResult = await getShopPlatformByClientId(clientId); - console.log('🔍 Platform check result:', platformResult); - if (platformResult.success && platformResult.data) { // Platform exists, use it finalPlatformId = platformResult.data.id; - console.log('✅ Found existing platform ID:', finalPlatformId, 'Name:', platformResult.data.name); } else { // Platform doesn't exist, will create inline with shop - console.log('📦 Platform does not exist, will create inline'); finalPlatformId = null; } } @@ -169,26 +156,24 @@ export function CreateShopFromURL({ onShopCreated, searchParams }: CreateShopFro } // Create the shop - const shopData: any = { + const shopData: CreateShopInput = { name: name.trim(), domain: domain.trim(), accessToken: finalAccessToken.trim(), - ...(refreshToken && { refreshToken: refreshToken }), - ...(tokenExpiresAt && { tokenExpiresAt: new Date(tokenExpiresAt) }), }; - console.log('🏪 Creating shop with data:'); - console.log(' - finalPlatformId:', finalPlatformId); - console.log(' - isMarketplaceFlow:', isMarketplaceFlow); - console.log(' - clientId:', clientId); - console.log(' - adapterSlug:', adapterSlug); + if (refreshToken) { + shopData.refreshToken = refreshToken; + } + + if (tokenExpiresAt) { + shopData.tokenExpiresAt = new Date(tokenExpiresAt); + } if (finalPlatformId) { - console.log('🔗 Using existing platform ID:', finalPlatformId); shopData.platformId = finalPlatformId; } else if (isMarketplaceFlow && clientId && clientSecret && appName && adapterSlug) { // Create platform inline using dynamic adapter slug - console.log('📦 Creating platform inline with adapter:', adapterSlug); shopData.platform = { create: { name: appName + ' (Auto-created)', @@ -211,19 +196,21 @@ export function CreateShopFromURL({ onShopCreated, searchParams }: CreateShopFro deleteWebhookFunction: adapterSlug, } }; - console.log('📦 Platform inline creation data:', shopData.platform.create); - } else { - console.log('❌ No platform connection - this will cause an error'); - console.log('❌ Missing: finalPlatformId?', !finalPlatformId, 'isMarketplaceFlow?', !isMarketplaceFlow, 'clientId?', !clientId, 'adapterSlug?', !adapterSlug); } - console.log('🏪 Final shopData before createShop call:', JSON.stringify(shopData, null, 2)); - const shopResult = await createShop(shopData); if (shopResult.success) { toast.success('Shop connected successfully!'); setIsDialogOpen(false); + + // Clean URL params after successful creation + const newUrl = new URL(window.location.href); + ['showCreateShop', 'platform', 'accessToken', 'domain', 'client_id', 'client_secret', 'app_name', 'adapter_slug', 'refreshToken', 'tokenExpiresAt', 'code'].forEach(param => { + newUrl.searchParams.delete(param); + }); + router.replace(newUrl.pathname + newUrl.search); + router.refresh(); if (onShopCreated) { @@ -259,10 +246,10 @@ export function CreateShopFromURL({ onShopCreated, searchParams }: CreateShopFro - Connect OpenFront Store + Connect Openfront Store {isMarketplaceFlow - ? 'Setting up your OpenFront integration. We\'ll create the platform if needed and connect your store.' + ? 'Setting up your Openfront integration. We\'ll create the platform if needed and connect your store.' : 'Complete your shop setup with the OAuth credentials received.' } @@ -308,7 +295,7 @@ export function CreateShopFromURL({ onShopCreated, searchParams }: CreateShopFro {isMarketplaceFlow && (

- openfront Integration + Openfront Integration

This platform will be created with the shop.