Last active
September 24, 2021 21:59
-
-
Save mshick/7ed492b8cb695c7dc23cc70ddf99ab48 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { | |
FieldNode, | |
OperationDefinitionNode, | |
SelectionNode, | |
SelectionSetNode, | |
getVisitFn, | |
Kind, | |
ASTNode, | |
DocumentNode, | |
visit, | |
BREAK, | |
GraphQLResolveInfo, | |
} from "graphql"; | |
import { Path } from "graphql/jsutils/Path"; | |
import { | |
ProjectSchema, | |
ContentSchema, | |
Query, | |
Shape, | |
getRefShapeName, | |
splitMapping, | |
findMapping, | |
createSchemaPropertyAccessor, | |
} from "@takeshape/schema"; | |
import { ASTKindToNode } from "graphql/language/ast"; | |
import { Visitor, VisitFn } from "graphql/language/visitor"; | |
import { isOperationDefinitionNode } from "../types"; | |
import { BadDataError } from "@takeshape/errors"; | |
export function getOperation(doc: DocumentNode): OperationDefinitionNode { | |
const operationDefinition = doc.definitions[0]; | |
if (!isOperationDefinitionNode(operationDefinition)) { | |
throw new BadDataError("Invalid selectionSet"); | |
} | |
return operationDefinition; | |
} | |
function hasName(node: SelectionNode, name: string): boolean { | |
return ( | |
("name" in node && node.name.value === name) || | |
("alias" in node && node.alias?.value === name) | |
); | |
} | |
export function pathToOperationPath(path: Path): string[] { | |
if (path.prev) { | |
const result = pathToOperationPath(path.prev); | |
return typeof path.key === "string" ? result.concat(path.key) : result; | |
} | |
return typeof path.key === "string" ? [path.key] : []; | |
} | |
export function followPath( | |
selection: { selectionSet?: SelectionSetNode }, | |
path: string[], | |
i = 0 | |
): SelectionNode | undefined { | |
if (selection.selectionSet) { | |
for (const node of selection.selectionSet.selections) { | |
if (hasName(node, path[i])) { | |
if (i === path.length - 1) { | |
return node; | |
} | |
return "selectionSet" in node | |
? followPath(node, path, i + 1) | |
: undefined; | |
} | |
} | |
} | |
} | |
export function getSelectionSetNames(node: FieldNode): string[] { | |
const result: string[] = []; | |
if (node.selectionSet) { | |
for (const selection of node.selectionSet.selections) { | |
if ("name" in selection && selection.name.value) { | |
result.push(selection.name.value); | |
} | |
} | |
} | |
return result; | |
} | |
export function getParentSelectionNames( | |
op: OperationDefinitionNode, | |
path: Path | |
): string[] { | |
const opPath = pathToOperationPath(path); | |
const parentOpPath = opPath.slice(0, opPath.length - 1); | |
const node = followPath(op, parentOpPath); | |
return node ? getSelectionSetNames(node as FieldNode) : []; | |
} | |
function isNode(maybeNode: any): maybeNode is ASTNode { | |
return Boolean(maybeNode && typeof maybeNode.kind === "string"); | |
} | |
export interface SchemaInfo { | |
path: string[]; | |
propertySchema?: ContentSchema; | |
shape?: Shape; | |
operationConfig?: Query; | |
operationType?: "query" | "mutation" | "subscription"; | |
projectSchema: ProjectSchema; | |
} | |
type VisitFnParams = Parameters<VisitFn<any>>; | |
export interface SchemaInfoVisitor { | |
enter( | |
node: VisitFnParams[0], | |
key: VisitFnParams[1], | |
parent: VisitFnParams[2], | |
path: VisitFnParams[3], | |
ancestors: VisitFnParams[4] | |
): void; | |
leave( | |
node: VisitFnParams[0], | |
key: VisitFnParams[1], | |
parent: VisitFnParams[2], | |
path: VisitFnParams[3], | |
ancestors: VisitFnParams[4] | |
): void; | |
getInfo(): SchemaInfo; | |
} | |
interface ShapeStackItem { | |
shape: Shape; | |
path: string[]; | |
} | |
// export function createSchemaInfoVisitor(projectSchema: ProjectSchema, shapeName: string): SchemaInfoVisitor { | |
// const createShapePropertyAccessor = createSchemaPropertyAccessor(projectSchema); | |
// let path: string[] = []; | |
// let propertySchema: ContentSchema | undefined; | |
// let shape: Shape | undefined = projectSchema.shapes[shapeName]; | |
// const shapeStackItem: ShapeStackItem | undefined = shape && { | |
// shape, | |
// path: ['shapes', shape.name, 'schema', 'properties'] | |
// }; | |
// const shapeStack: ShapeStackItem[] = shapeStackItem ? [shapeStackItem] : []; | |
// return { | |
// // eslint-disable-next-line max-params | |
// enter(node: ASTNode, key, parent, path, ancestors) { | |
// console.log('==================================entering'); | |
// if (node.kind === Kind.FIELD) { | |
// if (shapeStack.length) { | |
// console.log({key, parent, path, ancestors}); | |
// // console.log(node); | |
// ({shape} = shapeStack[shapeStack.length - 1]); | |
// console.log(shape.name, node.name.value); | |
// const schemaPropertyAccessor = createShapePropertyAccessor(shape.schema); | |
// path = ['shapes', shape.name, 'schema', 'properties', node.name.value]; | |
// propertySchema = schemaPropertyAccessor.getValue(node.name.value); | |
// if (propertySchema) { | |
// const shapeName = getRefShapeName(projectSchema, propertySchema?.items ?? propertySchema); | |
// if (shapeName) { | |
// // console.log('pushing-------', shapeName); | |
// shapeStack.push({shape: projectSchema.shapes[shapeName]}); | |
// } | |
// } | |
// } | |
// } | |
// }, | |
// leave(node: ASTNode, key): void { | |
// // console.log('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>leaving'); | |
// // console.log({key}); | |
// // if (node.kind === Kind.FIELD) { | |
// // console.log(node); | |
// // console.log(node.name.value); | |
// // } | |
// if (node.kind === Kind.SELECTION_SET) { | |
// // console.log(node.selections[0].name); | |
// shapeStack.pop(); | |
// } | |
// }, | |
// getInfo(): SchemaInfo { | |
// return { | |
// projectSchema, | |
// path, | |
// propertySchema, | |
// shape | |
// }; | |
// } | |
// }; | |
// } | |
export function createSchemaInfoVisitor( | |
projectSchema: ProjectSchema, | |
shapeName: string | |
): SchemaInfoVisitor { | |
let path: string[] = []; | |
let propertySchema: ContentSchema | undefined; | |
let shape: Shape | undefined = projectSchema.shapes[shapeName]; | |
const shapeStack: Shape[] = shape ? [shape] : []; | |
const createShapePropertyAccessor = | |
createSchemaPropertyAccessor(projectSchema); | |
return { | |
enter(node: ASTNode, key, parent, path, ancestors) { | |
// console.log('ENTERING-----------------'); | |
// console.log('PARENT>>>'); | |
// console.log(parent); | |
// console.log('ANCESTORS>>>>'); | |
// console.log(ancestors[0]?.selections); | |
if (node.kind === Kind.FIELD) { | |
if (shapeStack.length) { | |
shape = shapeStack[shapeStack.length - 1]; | |
// console.log({shapeName: shape.name}); | |
const schemaPropertyAccessor = createShapePropertyAccessor( | |
shape.schema | |
); | |
path = [ | |
"shapes", | |
shape.name, | |
"schema", | |
"properties", | |
node.name.value, | |
]; | |
// console.log(path); | |
propertySchema = schemaPropertyAccessor.getValue(node.name.value); | |
if (propertySchema) { | |
const shapeName = getRefShapeName( | |
projectSchema, | |
propertySchema?.items ?? propertySchema | |
); | |
if (shapeName) { | |
shapeStack.push(projectSchema.shapes[shapeName]); | |
} | |
} | |
} | |
} | |
}, | |
leave(node: ASTNode, key, parent, path, ancestors): void { | |
// console.log('----------------LEAVING'); | |
// console.log('PARENT>>>'); | |
// console.log(parent); | |
// console.log('ANCESTORS>>>>'); | |
// console.log(ancestors[0]?.selections); | |
if (node.kind === Kind.SELECTION_SET) { | |
shapeStack.pop(); | |
} | |
}, | |
getInfo(): SchemaInfo { | |
return { | |
projectSchema, | |
path, | |
propertySchema, | |
shape, | |
}; | |
}, | |
}; | |
} | |
export function visitWithSchemaInfo( | |
schemaInfoVisitor: SchemaInfoVisitor, | |
visitor: Visitor<ASTKindToNode> | |
): Visitor<ASTKindToNode> { | |
return { | |
// eslint-disable-next-line max-params | |
enter(node, key, parent, path, visitors) { | |
schemaInfoVisitor.enter(node, key, parent, path, visitors); | |
const fn = getVisitFn(visitor, node.kind, false); | |
if (fn) { | |
let result = fn.apply(visitor, arguments as any); | |
if (result !== undefined) { | |
schemaInfoVisitor.leave(node, key, parent, path, visitors); | |
if (isNode(result)) { | |
schemaInfoVisitor.enter(result, key, parent, path, visitors); | |
} | |
} | |
return result; | |
} | |
}, | |
// eslint-disable-next-line max-params | |
leave(node, key, parent, path, visitors) { | |
const fn = getVisitFn(visitor, node.kind, true); | |
let result; | |
if (fn) { | |
result = fn.apply(visitor, arguments as any); | |
} | |
schemaInfoVisitor.leave(node, key, parent, path, visitors); | |
return result; | |
}, | |
}; | |
} | |
/** | |
* Transform the query selection set to match the remote schema | |
* @param info | |
* @param projectSchema | |
* @param serviceId | |
*/ | |
export function transformSelectionSet( | |
info: Pick<GraphQLResolveInfo, "fieldNodes" | "returnType">, | |
projectSchema: ProjectSchema, | |
serviceId: string | |
): SelectionSetNode { | |
const shapeName = info.returnType.toString(); | |
const schemaInfoVisitor = createSchemaInfoVisitor(projectSchema, shapeName); | |
const visitor = visitWithSchemaInfo(schemaInfoVisitor, { | |
Field: { | |
enter(node) { | |
const { path } = schemaInfoVisitor.getInfo(); | |
console.log("///////////////////////////path"); | |
console.log(path); | |
const { propertySchema } = schemaInfoVisitor.getInfo(); | |
if (propertySchema) { | |
const mapping = findMapping(propertySchema, (mapping) => | |
mapping.startsWith(serviceId) | |
); | |
if (mapping) { | |
return { | |
...node, | |
name: { ...node.name, value: splitMapping(mapping)[1] }, | |
}; | |
} | |
return null; // delete this node | |
} | |
}, | |
}, | |
}); | |
const selectionSet = info.fieldNodes[0]?.selectionSet; | |
if (!selectionSet) { | |
throw new Error("Missing selectionSet"); | |
} | |
return visit(selectionSet, visitor); | |
} | |
export const PARENT_FRAGMENT = "_parentFragment"; | |
export function hasParentFragment( | |
selectionSet: SelectionSetNode | |
): string[] | undefined { | |
let path: string[] = []; | |
let result = false; | |
visit(selectionSet, { | |
Field: { | |
enter(node) { | |
path.push(node.alias ? node.alias.value : node.name.value); | |
}, | |
leave() { | |
path.pop(); | |
}, | |
}, | |
FragmentSpread: { | |
enter(node) { | |
if (node.name.value === PARENT_FRAGMENT) { | |
result = true; | |
return BREAK; | |
} | |
}, | |
}, | |
}); | |
return result ? path : undefined; | |
} | |
function parentFragmentPredicate(selection: SelectionNode): boolean { | |
return ( | |
selection.kind === Kind.FRAGMENT_SPREAD && | |
selection.name.value === PARENT_FRAGMENT | |
); | |
} | |
function parentFragmentNotPredicate(selection: SelectionNode): boolean { | |
return !parentFragmentPredicate(selection); | |
} | |
export function inlineParentFragment( | |
selectionSet: SelectionSetNode, | |
parentSelectionSet: SelectionSetNode | |
): SelectionSetNode { | |
return visit(selectionSet, { | |
SelectionSet(node) { | |
for (const selection of node.selections) { | |
if (parentFragmentPredicate(selection)) { | |
return { | |
...node, | |
selections: [ | |
...parentSelectionSet.selections, | |
...node.selections.filter(parentFragmentNotPredicate), | |
], | |
}; | |
} | |
} | |
}, | |
}); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"projectId": "4c54da75-a240-4e50-8343-bd1e8eafcdbb", | |
"dataKey": "AQIDAHhcZWXOdlBglkxBhI23ElO/clC/kuw5ynjXDSqJgfTz8gFW5RUbr2gMJW3lg7GcBv3HAAAAfjB8BgkqhkiG9w0BBwagbzBtAgEAMGgGCSqGSIb3DQEHATAeBglghkgBZQMEAS4wEQQMTQd9cbrxRTzTb3wuAgEQgDtorC3D/DOEoAguUH+McQKuH70cJWf7QnG1l0KQpmQDXwYY7z0+JYlEKyeXcqxOV+Lmp3JLmeesn6YbIQ==", | |
"version": 16, | |
"created": "2021-09-22T21:40:56.849Z", | |
"updated": "2021-09-24T18:42:24.966Z", | |
"defaultLocale": "en-us", | |
"locales": ["en-us"], | |
"apiVersion": "2", | |
"schemaVersion": "3.6.0", | |
"queries": { | |
"getShopifyProductDetails": { | |
"shape": "michaels-store-takeshape:Product", | |
"resolver": { | |
"id": "product", | |
"name": "graphql:query", | |
"service": "michaels-store-takeshape", | |
"options": { | |
"fieldName": "product", | |
"selectionSet": "{ ..._parentFragment metafields(first: 10) { edges { node { id namespace ownerType value description key } } } }" | |
}, | |
"argsMapping": { "id": [["get", { "path": "args.id" }]] } | |
}, | |
"description": "Returns Shopify Details", | |
"args": "ShopifyProductDetailsInput" | |
}, | |
"getProduct": { | |
"shape": "Product", | |
"resolver": { | |
"name": "takeshape:get", | |
"service": "takeshape:local", | |
"options": { "model": "Product" } | |
}, | |
"description": "Get a Product by ID", | |
"args": "TSGetArgs<Product>" | |
}, | |
"getProductList": { | |
"shape": "PaginatedList<Product>", | |
"resolver": { | |
"name": "takeshape:list", | |
"service": "takeshape:local", | |
"options": { "model": "Product" } | |
}, | |
"description": "Returns a list Product in natural order.", | |
"args": "TSListArgs<Product>" | |
} | |
}, | |
"mutations": { | |
"updateProduct": { | |
"shape": "UpdateResult<Product>", | |
"resolver": { | |
"compose": [ | |
{ | |
"id": "createNewShopifyObject", | |
"if": "isEmpty(args.input.shopifyProductId) && !isEmpty(args.input.shopifyProduct)", | |
"argsMapping": { | |
"input.descriptionHtml": [ | |
["get", { "path": "args.input.shopifyProduct.descriptionHtml" }] | |
], | |
"input.handle": [ | |
["get", { "path": "args.input.shopifyProduct.handle" }] | |
], | |
"input.redirectNewHandle": [ | |
[ | |
"get", | |
{ "path": "args.input.shopifyProduct.redirectNewHandle" } | |
] | |
], | |
"input.productType": [ | |
["get", { "path": "args.input.shopifyProduct.productType" }] | |
], | |
"input.tags": [ | |
["get", { "path": "args.input.shopifyProduct.tags" }] | |
], | |
"input.templateSuffix": [ | |
["get", { "path": "args.input.shopifyProduct.templateSuffix" }] | |
], | |
"input.giftCard": [ | |
["get", { "path": "args.input.shopifyProduct.giftCard" }] | |
], | |
"input.giftCardTemplateSuffix": [ | |
[ | |
"get", | |
{ "path": "args.input.shopifyProduct.giftCardTemplateSuffix" } | |
] | |
], | |
"input.title": [ | |
["get", { "path": "args.input.shopifyProduct.title" }] | |
], | |
"input.vendor": [ | |
["get", { "path": "args.input.shopifyProduct.vendor" }] | |
], | |
"input.bodyHtml": [ | |
["get", { "path": "args.input.shopifyProduct.bodyHtml" }] | |
] | |
}, | |
"name": "graphql:mutation", | |
"service": "michaels-store-takeshape", | |
"options": { | |
"fieldName": "productCreate", | |
"selectionSet": "{ product { id } }" | |
} | |
}, | |
{ | |
"id": "editTakeshape", | |
"argsMapping": { | |
"input": [["get", { "path": "args.input" }]], | |
"input.shopifyProductId": [ | |
["get", { "path": "steps.createNewShopifyObject.product.id" }], | |
["get", { "path": "args.input.shopifyProductId" }] | |
] | |
}, | |
"name": "takeshape:update", | |
"service": "takeshape:local", | |
"options": { "model": "Product" } | |
}, | |
{ | |
"id": "updateExistingShopifyObject", | |
"if": "!isEmpty(args.input.shopifyProductId) && !isEmpty(args.input.shopifyProduct)", | |
"argsMapping": { | |
"input.descriptionHtml": [ | |
["get", { "path": "args.input.shopifyProduct.descriptionHtml" }] | |
], | |
"input.handle": [ | |
["get", { "path": "args.input.shopifyProduct.handle" }] | |
], | |
"input.redirectNewHandle": [ | |
[ | |
"get", | |
{ "path": "args.input.shopifyProduct.redirectNewHandle" } | |
] | |
], | |
"input.productType": [ | |
["get", { "path": "args.input.shopifyProduct.productType" }] | |
], | |
"input.tags": [ | |
["get", { "path": "args.input.shopifyProduct.tags" }] | |
], | |
"input.templateSuffix": [ | |
["get", { "path": "args.input.shopifyProduct.templateSuffix" }] | |
], | |
"input.giftCard": [ | |
["get", { "path": "args.input.shopifyProduct.giftCard" }] | |
], | |
"input.giftCardTemplateSuffix": [ | |
[ | |
"get", | |
{ "path": "args.input.shopifyProduct.giftCardTemplateSuffix" } | |
] | |
], | |
"input.title": [ | |
["get", { "path": "args.input.shopifyProduct.title" }] | |
], | |
"input.vendor": [ | |
["get", { "path": "args.input.shopifyProduct.vendor" }] | |
], | |
"input.bodyHtml": [ | |
["get", { "path": "args.input.shopifyProduct.bodyHtml" }] | |
], | |
"input.id": [["get", { "path": "args.input.shopifyProductId" }]] | |
}, | |
"name": "graphql:mutation", | |
"service": "michaels-store-takeshape", | |
"options": { | |
"fieldName": "productUpdate", | |
"selectionSet": "{ product { id } }" | |
} | |
} | |
], | |
"resultsMapping": { | |
"result": [["get", { "path": "steps.editTakeshape.result" }]] | |
} | |
}, | |
"description": "Update Product. If the input has Shopify values and a Shopify ID, the Shopify product with that ID is updated.\nIf the input has Shopify values and no Shopify ID, a Shopify product is created.", | |
"args": "UpdateArgs<ProductInterface>" | |
}, | |
"createProduct": { | |
"shape": "CreateResult<Product>", | |
"resolver": { | |
"compose": [ | |
{ | |
"id": "shopifyCreate", | |
"if": "!isEmpty(args.input.shopifyProduct)", | |
"argsMapping": { | |
"input.descriptionHtml": [ | |
["get", { "path": "args.input.shopifyProduct.descriptionHtml" }] | |
], | |
"input.handle": [ | |
["get", { "path": "args.input.shopifyProduct.handle" }] | |
], | |
"input.redirectNewHandle": [ | |
[ | |
"get", | |
{ "path": "args.input.shopifyProduct.redirectNewHandle" } | |
] | |
], | |
"input.productType": [ | |
["get", { "path": "args.input.shopifyProduct.productType" }] | |
], | |
"input.tags": [ | |
["get", { "path": "args.input.shopifyProduct.tags" }] | |
], | |
"input.templateSuffix": [ | |
["get", { "path": "args.input.shopifyProduct.templateSuffix" }] | |
], | |
"input.giftCard": [ | |
["get", { "path": "args.input.shopifyProduct.giftCard" }] | |
], | |
"input.giftCardTemplateSuffix": [ | |
[ | |
"get", | |
{ "path": "args.input.shopifyProduct.giftCardTemplateSuffix" } | |
] | |
], | |
"input.title": [ | |
["get", { "path": "args.input.shopifyProduct.title" }] | |
], | |
"input.vendor": [ | |
["get", { "path": "args.input.shopifyProduct.vendor" }] | |
], | |
"input.bodyHtml": [ | |
["get", { "path": "args.input.shopifyProduct.bodyHtml" }] | |
] | |
}, | |
"name": "graphql:mutation", | |
"service": "michaels-store-takeshape", | |
"options": { | |
"fieldName": "productCreate", | |
"selectionSet": "{ product { id } }" | |
} | |
}, | |
{ | |
"id": "creatingShopifyObject", | |
"if": "!isEmpty(args.input.shopifyProduct)", | |
"argsMapping": { | |
"input": [["get", { "path": "args.input" }]], | |
"input.shopifyProductId": [ | |
["get", { "path": "steps.shopifyCreate.product.id" }] | |
] | |
}, | |
"name": "takeshape:create", | |
"service": "takeshape:local", | |
"options": { "model": "Product" } | |
}, | |
{ | |
"id": "notCreatingShopifyObject", | |
"if": "isEmpty(args.input.shopifyProduct)", | |
"argsMapping": { "input": [["get", { "path": "args.input" }]] }, | |
"name": "takeshape:create", | |
"service": "takeshape:local", | |
"options": { "model": "Product" } | |
} | |
], | |
"resultsMapping": { | |
"result": [ | |
["get", { "path": "steps.creatingShopifyObject.result" }], | |
["get", { "path": "steps.notCreatingShopifyObject.result" }] | |
] | |
} | |
}, | |
"description": "Create Product. If Shopify values are provided, a Shopify product is also created and the new product ID is saved.", | |
"args": "CreateArgs<ProductInterface>" | |
}, | |
"duplicateProduct": { | |
"shape": "DuplicateResult<Product>", | |
"resolver": { | |
"name": "takeshape:duplicate", | |
"service": "takeshape:local", | |
"options": { "model": "Product" } | |
}, | |
"description": "Duplicate Product", | |
"args": "DuplicateArgs<Product>" | |
}, | |
"deleteProduct": { | |
"shape": "DeleteResult<Product>", | |
"resolver": { | |
"name": "takeshape:delete", | |
"service": "takeshape:local", | |
"options": { "model": "Product" } | |
}, | |
"description": "Delete Product", | |
"args": "DeleteArgs<Product>" | |
} | |
}, | |
"shapes": { | |
"ProductInterface": { | |
"id": "ProductInterface", | |
"name": "ProductInterface", | |
"title": "ProductInterface", | |
"description": "ProductInterface", | |
"schema": { | |
"type": "object", | |
"properties": { | |
"_id": { "type": "string" }, | |
"_version": { "type": "number" }, | |
"_status": { "type": "string", "@workflow": "default" }, | |
"name": { | |
"title": "Name", | |
"type": "string", | |
"description": "Initialized with title from shopify" | |
}, | |
"shopifyProductId": { "title": "Service ID", "type": "string" }, | |
"shopifyProduct": { "@ref": "michaels-store-takeshape:ProductInput" } | |
}, | |
"required": [] | |
} | |
}, | |
"ProductAttributes": { | |
"id": "attribute-id", | |
"name": "ProductAttributes", | |
"title": "ProductAttributes", | |
"schema": { | |
"type": "object", | |
"properties": { | |
"name": { "type": "string" }, | |
"description": { "type": "string" }, | |
"type": { "type": "string" }, | |
"value": { "type": "string" } | |
} | |
} | |
}, | |
"ShopifyProductDetailsInput": { | |
"id": "ShopifyProductDetailsInput", | |
"name": "ShopifyProductDetailsInput", | |
"title": "ShopifyProductDetailsInput", | |
"schema": { | |
"type": "object", | |
"properties": { "id": { "type": "string" } }, | |
"required": ["id"] | |
} | |
}, | |
"Character": { | |
"id": "Character", | |
"name": "Character", | |
"title": "Character", | |
"schema": { | |
"type": "object", | |
"properties": { "name": { "type": "string" } } | |
} | |
}, | |
"Shopify_Product": { | |
"name": "Shopify_Product", | |
"title": "Shopify_Product", | |
"id": "Shopify_Product", | |
"description": "The Product resource lets you manage products in a merchant’s store. You can use [ProductVariants](https://shopify.dev/docs/admin-api/graphql/reference/products-and-collections/productvariant)\nto create or update different versions of the same product. You can also add or update product [Media](https://shopify.dev/docs/admin-api/graphql/reference/products-and-collections/media).\nProducts can be organized by grouping them into a [Collection](https://shopify.dev/docs/admin-api/graphql/reference/products-and-collections/collection).", | |
"schema": { | |
"type": "object", | |
"properties": { | |
"character": { | |
"$ref": "#/shapes/Character/schema", | |
"type": "object", | |
"title": "Character", | |
"@resolver": { | |
"name": "rest:post", | |
"service": "rick", | |
"options": { "path": "/character/1" } | |
} | |
}, | |
"attributes": { | |
"items": { "$ref": "#/shapes/ProductAttributes/schema" }, | |
"type": "array", | |
"@resolver": { | |
"resultsMapping": [ | |
[ | |
"expressionEval", | |
{ | |
"expression": "map(compose(compose(zipObject(['description', 'id', 'name', 'namespace', 'type', 'value']), map(get('[1]'))), sortBy('[0]'), toPairs, get('node')), get('metafields.edges', steps[0]))" | |
} | |
] | |
], | |
"name": "graphql:query", | |
"service": "michaels-store-takeshape", | |
"options": { | |
"fieldName": "product", | |
"selectionSet": "{ metafields(first: 10) { edges { node { id namespace ownerType value description key } } } }" | |
}, | |
"argsMapping": { "id": [["get", { "path": "source.id" }]] } | |
} | |
}, | |
"availablePublicationCount": { | |
"type": "integer", | |
"@mapping": "michaels-store-takeshape:Product.availablePublicationCount", | |
"description": "The number of publications a resource is published to without feedback errors." | |
}, | |
"bodyHtml": { | |
"type": "string", | |
"@mapping": "michaels-store-takeshape:Product.bodyHtml", | |
"@deprecationReason": "Use `descriptionHtml` instead", | |
"description": "The description of the product, complete with HTML formatting." | |
}, | |
"collections": { | |
"@ref": "michaels-store-takeshape:CollectionConnection", | |
"@mapping": "michaels-store-takeshape:Product.collections", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
}, | |
"sortKey": { | |
"description": "Sort the underlying list by the given key.", | |
"enum": ["TITLE", "UPDATED_AT", "ID", "RELEVANCE"], | |
"default": "ID" | |
}, | |
"query": { | |
"type": "string", | |
"description": "Supported filter parameters:\n - `collection_type`\n - `publishable_status`\n - `published_status`\n - `title`\n - `updated_at`\n\nSee the detailed [search syntax](https://help.shopify.com/api/getting-started/search-syntax)\nfor more information about using filters." | |
} | |
} | |
}, | |
"description": "A list of the collections that include the product." | |
}, | |
"createdAt": { | |
"description": "The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) when the product was created.", | |
"@tag": "DateTime", | |
"@mapping": "michaels-store-takeshape:Product.createdAt" | |
}, | |
"defaultCursor": { | |
"type": "string", | |
"@mapping": "michaels-store-takeshape:Product.defaultCursor", | |
"description": "A default cursor that returns the single next record, sorted ascending by ID." | |
}, | |
"description": { | |
"type": "string", | |
"@mapping": "michaels-store-takeshape:Product.description", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"truncateAt": { | |
"type": "integer", | |
"description": "Truncates string after the given length." | |
} | |
} | |
}, | |
"description": "A stripped description of the product, single line with HTML tags removed." | |
}, | |
"descriptionHtml": { | |
"description": "The description of the product, complete with HTML formatting.", | |
"@tag": "HTML", | |
"@mapping": "michaels-store-takeshape:Product.descriptionHtml" | |
}, | |
"descriptionPlainSummary": { | |
"type": "string", | |
"@mapping": "michaels-store-takeshape:Product.descriptionPlainSummary", | |
"@deprecationReason": "Use `description` instead", | |
"description": "Stripped description of the product, single line with HTML tags removed.\nTruncated to 60 characters." | |
}, | |
"featuredImage": { | |
"@ref": "michaels-store-takeshape:Image", | |
"@mapping": "michaels-store-takeshape:Product.featuredImage", | |
"description": "The featured image for the product." | |
}, | |
"featuredMedia": { | |
"@ref": "michaels-store-takeshape:Media", | |
"@mapping": "michaels-store-takeshape:Product.featuredMedia", | |
"description": "The featured media for the product." | |
}, | |
"feedback": { | |
"@ref": "michaels-store-takeshape:ResourceFeedback", | |
"@mapping": "michaels-store-takeshape:Product.feedback", | |
"description": "Information about the product that's provided through resource feedback." | |
}, | |
"giftCardTemplateSuffix": { | |
"type": "string", | |
"@mapping": "michaels-store-takeshape:Product.giftCardTemplateSuffix", | |
"description": "The theme template used when viewing the gift card in a store." | |
}, | |
"handle": { | |
"type": "string", | |
"@mapping": "michaels-store-takeshape:Product.handle", | |
"description": "A unique human-friendly string of the product's title." | |
}, | |
"hasOnlyDefaultVariant": { | |
"type": "boolean", | |
"@mapping": "michaels-store-takeshape:Product.hasOnlyDefaultVariant", | |
"description": "Whether the product has only a single variant with the default option and value." | |
}, | |
"hasOutOfStockVariants": { | |
"type": "boolean", | |
"@mapping": "michaels-store-takeshape:Product.hasOutOfStockVariants", | |
"description": "Whether the product has out of stock variants." | |
}, | |
"id": { | |
"type": "string", | |
"@tag": "id", | |
"@mapping": "michaels-store-takeshape:Product.id", | |
"description": "A globally-unique identifier." | |
}, | |
"images": { | |
"@ref": "michaels-store-takeshape:ImageConnection", | |
"@mapping": "michaels-store-takeshape:Product.images", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
}, | |
"sortKey": { | |
"description": "Sort the underlying list by the given key.", | |
"enum": ["CREATED_AT", "POSITION", "ID", "RELEVANCE"], | |
"default": "POSITION" | |
}, | |
"maxWidth": { | |
"type": "integer", | |
"description": "Image width in pixels between 1 and 2048. This argument is deprecated: Use `maxWidth` on `Image.transformedSrc` instead." | |
}, | |
"maxHeight": { | |
"type": "integer", | |
"description": "Image height in pixels between 1 and 2048. This argument is deprecated: Use\n`maxHeight` on `Image.transformedSrc` instead." | |
}, | |
"crop": { | |
"description": "Crops the image according to the specified region. This argument is\ndeprecated: Use `crop` on `Image.transformedSrc` instead.", | |
"enum": ["CENTER", "TOP", "BOTTOM", "LEFT", "RIGHT"] | |
}, | |
"scale": { | |
"type": "integer", | |
"description": "Image size multiplier for high-resolution retina displays. Must be between 1\nand 3. This argument is deprecated: Use `scale` on `Image.transformedSrc` instead.", | |
"default": "1" | |
} | |
} | |
}, | |
"description": "The images associated with the product." | |
}, | |
"inCollection": { | |
"type": "boolean", | |
"@mapping": "michaels-store-takeshape:Product.inCollection", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"id": { | |
"type": "string", | |
"@tag": "id", | |
"description": "The ID of the collection to check." | |
} | |
}, | |
"required": ["id"] | |
}, | |
"description": "Whether the product is in a given collection." | |
}, | |
"isGiftCard": { | |
"type": "boolean", | |
"@mapping": "michaels-store-takeshape:Product.isGiftCard", | |
"description": "Whether the product is a gift card." | |
}, | |
"legacyResourceId": { | |
"description": "The ID of the corresponding resource in the REST Admin API.", | |
"@tag": "UnsignedInt64", | |
"@mapping": "michaels-store-takeshape:Product.legacyResourceId" | |
}, | |
"media": { | |
"@ref": "michaels-store-takeshape:MediaConnection", | |
"@mapping": "michaels-store-takeshape:Product.media", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
}, | |
"sortKey": { | |
"description": "Sort the underlying list by the given key.", | |
"enum": ["POSITION", "ID", "RELEVANCE"], | |
"default": "POSITION" | |
} | |
} | |
}, | |
"description": "The media associated with the product. This can include images, 3D models, or videos." | |
}, | |
"mediaCount": { | |
"type": "integer", | |
"@mapping": "michaels-store-takeshape:Product.mediaCount", | |
"description": "Total count of media belonging to a product." | |
}, | |
"metafield": { | |
"@ref": "michaels-store-takeshape:Metafield", | |
"@mapping": "michaels-store-takeshape:Product.metafield", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"namespace": { | |
"type": "string", | |
"description": "The namespace for the metafield." | |
}, | |
"key": { | |
"type": "string", | |
"description": "The key for the metafield." | |
} | |
}, | |
"required": ["namespace", "key"] | |
}, | |
"description": "Returns a metafield by namespace and key that belongs to the resource." | |
}, | |
"metafields": { | |
"@ref": "michaels-store-takeshape:MetafieldConnection", | |
"@mapping": "michaels-store-takeshape:Product.metafields", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"namespace": { | |
"type": "string", | |
"description": "The metafield namespace to filter by." | |
}, | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
} | |
} | |
}, | |
"description": "List of metafields that belong to the resource." | |
}, | |
"onlineStorePreviewUrl": { | |
"description": "The online store preview URL.", | |
"@tag": "URL", | |
"@mapping": "michaels-store-takeshape:Product.onlineStorePreviewUrl" | |
}, | |
"onlineStoreUrl": { | |
"description": "The online store URL for the product.\nA value of `null` indicates that the product is not published to the Online Store sales channel.", | |
"@tag": "URL", | |
"@mapping": "michaels-store-takeshape:Product.onlineStoreUrl" | |
}, | |
"options": { | |
"type": "array", | |
"items": { "@ref": "michaels-store-takeshape:ProductOption" }, | |
"@mapping": "michaels-store-takeshape:Product.options", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"first": { | |
"type": "integer", | |
"description": "Truncate the array result to this size." | |
} | |
} | |
}, | |
"description": "A list of product options. The limit is specified by Shop.resourceLimits.maxProductOptions." | |
}, | |
"priceRange": { | |
"@ref": "michaels-store-takeshape:ProductPriceRange", | |
"@mapping": "michaels-store-takeshape:Product.priceRange", | |
"@deprecationReason": "Deprecated in API version 2020-10. Use `priceRangeV2` instead.", | |
"description": "The price range of the product." | |
}, | |
"priceRangeV2": { | |
"@ref": "michaels-store-takeshape:ProductPriceRangeV2", | |
"@mapping": "michaels-store-takeshape:Product.priceRangeV2", | |
"description": "The price range of the product with prices formatted as decimals." | |
}, | |
"privateMetafield": { | |
"@ref": "michaels-store-takeshape:PrivateMetafield", | |
"@mapping": "michaels-store-takeshape:Product.privateMetafield", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"namespace": { | |
"type": "string", | |
"description": "The namespace for the private metafield." | |
}, | |
"key": { | |
"type": "string", | |
"description": "The key for the private metafield." | |
} | |
}, | |
"required": ["namespace", "key"] | |
}, | |
"description": "Returns a private metafield by namespace and key that belongs to the resource." | |
}, | |
"privateMetafields": { | |
"@ref": "michaels-store-takeshape:PrivateMetafieldConnection", | |
"@mapping": "michaels-store-takeshape:Product.privateMetafields", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"namespace": { | |
"type": "string", | |
"description": "Filter the private metafields by namespace." | |
}, | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
} | |
} | |
}, | |
"description": "List of private metafields that belong to the resource." | |
}, | |
"productPublications": { | |
"@ref": "michaels-store-takeshape:ProductPublicationConnection", | |
"@mapping": "michaels-store-takeshape:Product.productPublications", | |
"@deprecationReason": "Use `resourcePublications` instead", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
} | |
} | |
}, | |
"description": "A list of the channels where the product is published." | |
}, | |
"productType": { | |
"type": "string", | |
"@mapping": "michaels-store-takeshape:Product.productType", | |
"description": "The product type specified by the merchant." | |
}, | |
"publicationCount": { | |
"type": "integer", | |
"@mapping": "michaels-store-takeshape:Product.publicationCount", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"onlyPublished": { | |
"type": "boolean", | |
"description": "Include only the resource's publications that are published. If false, then\nreturn all the resource's publications including future publications.", | |
"default": true | |
} | |
} | |
}, | |
"description": "The number of publications a resource is published on." | |
}, | |
"publications": { | |
"@ref": "michaels-store-takeshape:ProductPublicationConnection", | |
"@mapping": "michaels-store-takeshape:Product.publications", | |
"@deprecationReason": "Use `resourcePublications` instead", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"onlyPublished": { | |
"type": "boolean", | |
"description": "Return only the publications that are published. If false, then return all publications.", | |
"default": true | |
}, | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
} | |
} | |
}, | |
"description": "A list of the channels where the product is published." | |
}, | |
"publishedAt": { | |
"description": "The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601))\nwhen the product was published to the Online Store.", | |
"@tag": "DateTime", | |
"@mapping": "michaels-store-takeshape:Product.publishedAt" | |
}, | |
"publishedOnChannel": { | |
"type": "boolean", | |
"@mapping": "michaels-store-takeshape:Product.publishedOnChannel", | |
"@deprecationReason": "Use `publishedOnPublication` instead", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"channelId": { | |
"type": "string", | |
"@tag": "id", | |
"description": "The ID of the channel to check." | |
} | |
}, | |
"required": ["channelId"] | |
}, | |
"description": "Check to see whether the resource is published to a given channel." | |
}, | |
"publishedOnCurrentChannel": { | |
"type": "boolean", | |
"@mapping": "michaels-store-takeshape:Product.publishedOnCurrentChannel", | |
"@deprecationReason": "Use `publishedOnCurrentPublication` instead", | |
"description": "Check to see whether the resource is published to the calling app's channel." | |
}, | |
"publishedOnCurrentPublication": { | |
"type": "boolean", | |
"@mapping": "michaels-store-takeshape:Product.publishedOnCurrentPublication", | |
"description": "Check to see whether the resource is published to the calling app's publication." | |
}, | |
"publishedOnPublication": { | |
"type": "boolean", | |
"@mapping": "michaels-store-takeshape:Product.publishedOnPublication", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"publicationId": { | |
"type": "string", | |
"@tag": "id", | |
"description": "The ID of the publication to check." | |
} | |
}, | |
"required": ["publicationId"] | |
}, | |
"description": "Check to see whether the resource is published to a given publication." | |
}, | |
"resourcePublications": { | |
"@ref": "michaels-store-takeshape:ResourcePublicationConnection", | |
"@mapping": "michaels-store-takeshape:Product.resourcePublications", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"onlyPublished": { | |
"type": "boolean", | |
"description": "Whether to return only the resources that are currently published. If false,\nthen also returns the resources that are scheduled to be published.", | |
"default": true | |
}, | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
} | |
} | |
}, | |
"description": "The list of resources that are published to a publication." | |
}, | |
"resourcePublicationsV2": { | |
"@ref": "michaels-store-takeshape:ResourcePublicationV2Connection", | |
"@mapping": "michaels-store-takeshape:Product.resourcePublicationsV2", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"onlyPublished": { | |
"type": "boolean", | |
"description": "Whether to return only the resources that are currently published. If false,\nthen also returns the resources that are scheduled or staged to be published.", | |
"default": true | |
}, | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
} | |
} | |
}, | |
"description": "The list of resources that are either published or staged to be published to a publication." | |
}, | |
"seo": { | |
"@ref": "michaels-store-takeshape:SEO", | |
"@mapping": "michaels-store-takeshape:Product.seo", | |
"description": "SEO information of the product." | |
}, | |
"status": { | |
"description": "The product status. This controls visibility across all channels.", | |
"enum": ["ACTIVE", "ARCHIVED", "DRAFT"], | |
"@mapping": "michaels-store-takeshape:Product.status" | |
}, | |
"storefrontId": { | |
"description": "The storefront ID of the product.", | |
"@tag": "StorefrontID", | |
"@mapping": "michaels-store-takeshape:Product.storefrontId" | |
}, | |
"tags": { | |
"type": "array", | |
"items": { "type": "string" }, | |
"@mapping": "michaels-store-takeshape:Product.tags", | |
"description": "A comma separated list of tags associated with the product. Updating `tags` overwrites\nany existing tags that were previously added to the product. To add new tags without overwriting\nexisting tags, use the [tagsAdd](https://shopify.dev/docs/admin-api/graphql/reference/common-objects/tagsadd)\nmutation." | |
}, | |
"templateSuffix": { | |
"type": "string", | |
"@mapping": "michaels-store-takeshape:Product.templateSuffix", | |
"description": "The theme template used when viewing the product in a store." | |
}, | |
"title": { | |
"type": "string", | |
"@mapping": "michaels-store-takeshape:Product.title", | |
"description": "The title of the product." | |
}, | |
"totalInventory": { | |
"type": "integer", | |
"@mapping": "michaels-store-takeshape:Product.totalInventory", | |
"description": "The quantity of inventory in stock." | |
}, | |
"totalVariants": { | |
"type": "integer", | |
"@mapping": "michaels-store-takeshape:Product.totalVariants", | |
"description": "The number of variants that are associated with the product." | |
}, | |
"tracksInventory": { | |
"type": "boolean", | |
"@mapping": "michaels-store-takeshape:Product.tracksInventory", | |
"description": "Whether inventory tracking has been enabled for the product." | |
}, | |
"translations": { | |
"type": "array", | |
"items": { | |
"@ref": "michaels-store-takeshape:PublishedTranslation" | |
}, | |
"@mapping": "michaels-store-takeshape:Product.translations", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"locale": { | |
"type": "string", | |
"description": "Filters translations locale." | |
} | |
}, | |
"required": ["locale"] | |
}, | |
"description": "The translations associated with the resource." | |
}, | |
"unpublishedChannels": { | |
"@ref": "michaels-store-takeshape:ChannelConnection", | |
"@mapping": "michaels-store-takeshape:Product.unpublishedChannels", | |
"@deprecationReason": "Use `unpublishedPublications` instead", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
} | |
} | |
}, | |
"description": "The list of channels that the resource is not published to." | |
}, | |
"unpublishedPublications": { | |
"@ref": "michaels-store-takeshape:PublicationConnection", | |
"@mapping": "michaels-store-takeshape:Product.unpublishedPublications", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
} | |
} | |
}, | |
"description": "The list of publications that the resource is not published to." | |
}, | |
"updatedAt": { | |
"description": "The date and time when the product was last modified.\nA product's `updatedAt` value can change for different reasons. For example, if an order\nis placed for a product that has inventory tracking set up, then the inventory adjustment\nis counted as an update.", | |
"@tag": "DateTime", | |
"@mapping": "michaels-store-takeshape:Product.updatedAt" | |
}, | |
"variants": { | |
"@ref": "michaels-store-takeshape:ProductVariantConnection", | |
"@mapping": "michaels-store-takeshape:Product.variants", | |
"@args": { | |
"type": "object", | |
"properties": { | |
"first": { | |
"type": "integer", | |
"description": "Returns up to the first `n` elements from the list." | |
}, | |
"after": { | |
"type": "string", | |
"description": "Returns the elements that come after the specified cursor." | |
}, | |
"last": { | |
"type": "integer", | |
"description": "Returns up to the last `n` elements from the list." | |
}, | |
"before": { | |
"type": "string", | |
"description": "Returns the elements that come before the specified cursor." | |
}, | |
"reverse": { | |
"type": "boolean", | |
"description": "Reverse the order of the underlying list.", | |
"default": false | |
}, | |
"sortKey": { | |
"description": "Sort the underlying list by the given key.", | |
"enum": [ | |
"TITLE", | |
"NAME", | |
"SKU", | |
"INVENTORY_QUANTITY", | |
"INVENTORY_MANAGEMENT", | |
"INVENTORY_LEVELS_AVAILABLE", | |
"INVENTORY_POLICY", | |
"FULL_TITLE", | |
"POPULAR", | |
"POSITION", | |
"ID", | |
"RELEVANCE" | |
], | |
"default": "POSITION" | |
} | |
} | |
}, | |
"description": "A list of variants associated with the product." | |
}, | |
"vendor": { | |
"type": "string", | |
"@mapping": "michaels-store-takeshape:Product.vendor", | |
"description": "The name of the product's vendor." | |
} | |
}, | |
"required": [ | |
"availablePublicationCount", | |
"collections", | |
"createdAt", | |
"defaultCursor", | |
"description", | |
"descriptionHtml", | |
"descriptionPlainSummary", | |
"handle", | |
"hasOnlyDefaultVariant", | |
"hasOutOfStockVariants", | |
"id", | |
"images", | |
"inCollection", | |
"isGiftCard", | |
"legacyResourceId", | |
"media", | |
"mediaCount", | |
"metafields", | |
"options", | |
"priceRange", | |
"priceRangeV2", | |
"privateMetafields", | |
"productPublications", | |
"productType", | |
"publicationCount", | |
"publications", | |
"publishedOnChannel", | |
"publishedOnCurrentChannel", | |
"publishedOnCurrentPublication", | |
"publishedOnPublication", | |
"resourcePublications", | |
"resourcePublicationsV2", | |
"seo", | |
"status", | |
"storefrontId", | |
"tags", | |
"title", | |
"totalInventory", | |
"totalVariants", | |
"tracksInventory", | |
"translations", | |
"unpublishedChannels", | |
"unpublishedPublications", | |
"updatedAt", | |
"variants", | |
"vendor" | |
] | |
} | |
}, | |
"Product": { | |
"name": "Product", | |
"id": "r_P4Zu5wr", | |
"title": "Product", | |
"workflow": "default", | |
"model": { "type": "multiple" }, | |
"schema": { | |
"type": "object", | |
"properties": { | |
"name": { | |
"title": "Name", | |
"type": "string", | |
"description": "Initialized with title from shopify", | |
"@mapping": "takeshape:local:Product.UAPS1KwbxZ" | |
}, | |
"shopifyProduct": { | |
"@ref": "michaels-store-takeshape:Product", | |
"@resolver": { | |
"name": "graphql:query", | |
"service": "michaels-store-takeshape", | |
"options": { "fieldName": "product" }, | |
"argsMapping": { | |
"id": [["get", { "path": "source.shopifyProductId" }]] | |
} | |
}, | |
"@tag": "pattern:service-object:1" | |
}, | |
"shopifyProductId": { | |
"type": "string", | |
"@mapping": "takeshape:local:Product.shopifyProductId", | |
"title": "shopify product", | |
"minLength": 1, | |
"pattern": "(^gid://shopify/Product/\\d+$)" | |
}, | |
"attributes": { | |
"items": { "$ref": "#/shapes/ProductAttributes/schema" }, | |
"type": "array", | |
"@resolver": { | |
"resultsMapping": [ | |
[ | |
"expressionEval", | |
{ | |
"expression": "map(compose(compose(zipObject(['description', 'id', 'name', 'namespace', 'type', 'value']), map(get('[1]'))), sortBy('[0]'), toPairs, get('node')), get('metafields.edges', steps[0]))" | |
} | |
] | |
], | |
"name": "graphql:query", | |
"service": "michaels-store-takeshape", | |
"options": { | |
"fieldName": "product", | |
"selectionSet": "{ metafields(first: 10) { edges { node { id namespace ownerType value description key } } } }" | |
}, | |
"argsMapping": { | |
"id": [["get", { "path": "source.shopifyProductId" }]] | |
} | |
} | |
} | |
} | |
} | |
} | |
}, | |
"workflows": {}, | |
"forms": { | |
"Product": { | |
"default": { | |
"properties": { | |
"name": { "widget": "singleLineText" }, | |
"shopifyProduct": { | |
"properties": { | |
"descriptionHtml": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"handle": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"redirectNewHandle": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"productType": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"tags": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"templateSuffix": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"giftCard": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"giftCardTemplateSuffix": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"title": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"vendor": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"bodyHtml": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"images": { | |
"widget": "shopifyProductImages", | |
"provider": "shopify" | |
}, | |
"publishedAt": { | |
"widget": "serviceObjectProperty", | |
"provider": "shopify" | |
}, | |
"variants": { | |
"widget": "shopifyRelationshipSummary", | |
"provider": "shopify" | |
} | |
}, | |
"widget": "shopify", | |
"wrapper": "shopifyServiceWrapper", | |
"order": [ | |
"title", | |
"handle", | |
"descriptionHtml", | |
"bodyHtml", | |
"tags", | |
"vendor", | |
"publishedAt", | |
"variants", | |
"images", | |
"redirectNewHandle", | |
"productType", | |
"templateSuffix", | |
"giftCard", | |
"giftCardTemplateSuffix" | |
] | |
}, | |
"shopifyProductId": { | |
"instructions": "Format: gid://shopify/Product/1111111111111", | |
"label": "product ID", | |
"widget": "serviceObjectId", | |
"provider": "shopify", | |
"serviceObjectType": "product", | |
"service": "michaels-store-takeshape" | |
} | |
}, | |
"order": ["name", "shopifyProductId", "shopifyProduct"] | |
} | |
} | |
}, | |
"services": { | |
"michaels-store-takeshape": { | |
"title": "SHOPIFY", | |
"namespace": "Shopify", | |
"provider": "shopify", | |
"serviceType": "graphql", | |
"authenticationType": "oauth2Bearer", | |
"authentication": "6/gkgSypmOWoOV6gK31wos2tknamMHXmG7nqftu0WeWOzAVTbGOdGignhyVm+w9TocoBehgctDxiyrToGTTI5w7TUVN5yItDJAd4DO+sY9DOy8kMcvr17jKCZvj0m32e+YKVmg24AT3OsOuX/O64wPZ1zv8JAOEMDGnHLEZEOc+BQp9zJlXdOf9PMAxkmjxsVe/S", | |
"options": { | |
"shop": "michaels-store-takeshape", | |
"endpoint": "https://michaels-store-takeshape.myshopify.com/admin/api/2020-07/graphql.json" | |
}, | |
"id": "michaels-store-takeshape" | |
}, | |
"rick": { | |
"id": "rick", | |
"provider": "generic", | |
"title": "Rick", | |
"namespace": "Rick", | |
"serviceType": "rest", | |
"authenticationType": "none", | |
"options": { "endpoint": "https://rickandmortyapi.com/api" } | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment