From 9a68b90e59ab98246b79718578ee6276a51fa78b Mon Sep 17 00:00:00 2001 From: Christopher Pappas Date: Mon, 30 Aug 2021 15:45:29 -0700 Subject: [PATCH 1/6] wip - schema returned, delegateToSchema undefined --- package.json | 5 + src/config.ts | 3 + src/index.ts | 15 +- src/lib/stitching2/kaws/link.ts | 12 + src/lib/stitching2/kaws/schema.ts | 28 +++ src/lib/stitching2/kaws/v2/stitching.ts | 215 ++++++++++++++++++ .../stitching2/lib/createRemoteExecutor.ts | 66 ++++++ src/lib/stitching2/mergeSchemas.ts | 41 ++++ .../middleware/responseLoggerMiddleware.ts | 29 +++ src/schema/v2/index.ts | 51 +++-- yarn.lock | 166 ++++++++++++++ 11 files changed, 613 insertions(+), 18 deletions(-) create mode 100644 src/lib/stitching2/kaws/link.ts create mode 100644 src/lib/stitching2/kaws/schema.ts create mode 100644 src/lib/stitching2/kaws/v2/stitching.ts create mode 100644 src/lib/stitching2/lib/createRemoteExecutor.ts create mode 100644 src/lib/stitching2/mergeSchemas.ts create mode 100644 src/lib/stitching2/middleware/responseLoggerMiddleware.ts diff --git a/package.json b/package.json index df243f0bbf..c4015106b5 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,11 @@ "@babel/preset-typescript": "7.3.3", "@babel/register": "7.4.4", "@graphql-tools/delegate": "6.0.10", + "@graphql-tools/graphql-file-loader": "^7.0.6", + "@graphql-tools/load": "^7.1.9", + "@graphql-tools/schema": "^8.1.2", + "@graphql-tools/stitch": "^8.2.1", + "@graphql-tools/wrap": "^8.0.13", "@heroku/foreman": "2.0.2", "@sentry/node": "5.18.1", "accounting": "0.4.1", diff --git a/src/config.ts b/src/config.ts index 430e74dcf6..9fb08f18f4 100644 --- a/src/config.ts +++ b/src/config.ts @@ -37,6 +37,7 @@ const { ENABLE_QUERY_TRACING, ENABLE_REQUEST_LOGGING, DISABLE_SCHEMA_STITCHING, + ENABLE_EXPERIMENTAL_STITCHING_MIGRATION, ENABLE_RESOLVER_BATCHING, EXCHANGE_API_BASE, EXCHANGE_APP_ID, @@ -162,6 +163,8 @@ export default { EMBEDLY_KEY, ENABLE_APOLLO: ENABLE_APOLLO === "true", ENABLE_ASYNC_STACK_TRACES, + ENABLE_EXPERIMENTAL_STITCHING_MIGRATION: + ENABLE_EXPERIMENTAL_STITCHING_MIGRATION === "true", ENABLE_METRICS, ENABLE_QUERY_TRACING, ENABLE_REQUEST_LOGGING, diff --git a/src/index.ts b/src/index.ts index c06a2c038d..05e2ec11cf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,7 +9,7 @@ import { createLoaders } from "./lib/loaders" import depthLimit from "graphql-depth-limit" import express from "express" import { schema as schemaV1 } from "./schema/v1" -import { schema as schemaV2 } from "./schema/v2" +import { getSchema as getSchemaV2 } from "./schema/v2" import moment from "moment-timezone" import morgan from "artsy-morgan" import { fetchPersistedQuery } from "./lib/fetchPersistedQuery" @@ -267,8 +267,15 @@ function startApp(appSchema, path: string) { const app = express() -// This order is important for dd-trace to be able to find the nested routes. -app.use("/v2", startApp(schemaV2, "/")) -app.use("/", startApp(schemaV1, "/")) +;(async () => { + try { + const schemaV2 = await getSchemaV2() + // This order is important for dd-trace to be able to find the nested routes. + app.use("/v2", (req, res, next) => startApp(schemaV2, "/")(req, res, next)) + app.use("/", (req, res, next) => startApp(schemaV1, "/")(req, res, next)) + } catch (error) { + console.log(error) + } +})() export default app diff --git a/src/lib/stitching2/kaws/link.ts b/src/lib/stitching2/kaws/link.ts new file mode 100644 index 0000000000..857217578f --- /dev/null +++ b/src/lib/stitching2/kaws/link.ts @@ -0,0 +1,12 @@ +import urljoin from "url-join" +import config from "config" +import { createRemoteExecutor } from "../lib/createRemoteExecutor" +import { responseLoggerMiddleware } from "../middleware/responseLoggerMiddleware" + +const { KAWS_API_BASE } = config + +export const createKawsExecutor = () => { + return createRemoteExecutor(urljoin(KAWS_API_BASE, "graphql"), { + middleware: [responseLoggerMiddleware("Kaws")], + }) +} diff --git a/src/lib/stitching2/kaws/schema.ts b/src/lib/stitching2/kaws/schema.ts new file mode 100644 index 0000000000..71549c716f --- /dev/null +++ b/src/lib/stitching2/kaws/schema.ts @@ -0,0 +1,28 @@ +import { createKawsExecutor } from "./link" +import { GraphQLFileLoader } from "@graphql-tools/graphql-file-loader" +import { RenameTypes, RenameRootFields } from "@graphql-tools/wrap" +import { loadSchema } from "@graphql-tools/load" +import { GraphQLSchema } from "graphql" + +export const executableKawsSchema = async () => { + const kawsExecutor = createKawsExecutor() + const kawsSchema: GraphQLSchema = await loadSchema("src/data/kaws.graphql", { + loaders: [new GraphQLFileLoader()], + }) + + const schema = { + schema: kawsSchema, + executor: kawsExecutor, + transforms: [ + new RenameTypes((name) => { + return `Marketing${name}` + }), + new RenameRootFields( + (_operation, name) => + `marketing${name.charAt(0).toUpperCase() + name.slice(1)}` + ), + ], + } + + return schema +} diff --git a/src/lib/stitching2/kaws/v2/stitching.ts b/src/lib/stitching2/kaws/v2/stitching.ts new file mode 100644 index 0000000000..c0d2f39e7c --- /dev/null +++ b/src/lib/stitching2/kaws/v2/stitching.ts @@ -0,0 +1,215 @@ +import { GraphQLSchema, GraphQLFieldConfigArgumentMap } from "graphql" +import { + pageableFilterArtworksArgsWithInput, + filterArtworksArgs, +} from "schema/v2/filterArtworksConnection" +import gql from "lib/gql" +import { printType } from "lib/stitching/lib/printType" + +export const kawsStitchingEnvironmentV2 = ( + localSchema: GraphQLSchema, + kawsSchema: GraphQLSchema & { transforms?: any } +) => { + return { + // The SDL used to declare how to stitch an object + extensionSchema: gql` + extend type Artist { + marketingCollections(slugs: [String!], category: String, randomizationSeed: String, size: Int, isFeaturedArtistContent: Boolean, showOnEditorial: Boolean): [MarketingCollection] + } + extend type Fair { + marketingCollections(size: Int): [MarketingCollection]! + } + extend type Viewer { + marketingCollections(slugs: [String!], category: String, randomizationSeed: String, size: Int, isFeaturedArtistContent: Boolean, showOnEditorial: Boolean, artistID: String): [MarketingCollection] + } + extend type MarketingCollection { + internalID: ID! + artworksConnection(${argsToSDL( + pageableFilterArtworksArgsWithInput + ).join("\n")}): FilterArtworksConnection + } + type HomePageMarketingCollectionsModule { + results: [MarketingCollection]! + } + extend type HomePage { + marketingCollectionsModule: HomePageMarketingCollectionsModule + } + `, + // Resolvers for the above, this passes in ALL potential parameters + // from KAWS into filter_artworks to allow end users to dynamically + // modify query filters using an admin tool + resolvers: { + Artist: { + marketingCollections: { + fragment: ` + ... on Artist { + internalID + } + `, + resolve: ({ internalID: artistID }, args, context, info) => { + return info.mergeInfo.delegateToSchema({ + schema: kawsSchema, + operation: "query", + fieldName: "marketingCollections", + + args: { + artistID, + ...args, + }, + context, + info, + }) + }, + }, + }, + Fair: { + marketingCollections: { + fragment: ` + ... on Fair { + kawsCollectionSlugs + } + `, + resolve: ({ kawsCollectionSlugs: slugs }, args, context, info) => { + if (slugs.length === 0) return [] + return info.mergeInfo.delegateToSchema({ + schema: kawsSchema, + operation: "query", + fieldName: "marketingCollections", + + args: { + slugs, + ...args, + }, + context, + info, + }) + }, + }, + }, + HomePage: { + marketingCollectionsModule: { + fragment: gql` + ... on HomePage { + __typename + } + `, + resolve: () => { + return {} + }, + }, + }, + HomePageMarketingCollectionsModule: { + results: { + fragment: gql` + ... on HomePageMarketingCollectionsModule { + __typename + } + `, + resolve: async (_source, _args, context, info) => { + try { + // We hard-code the collections slugs here in MP so that the app + // can display different collections based only on an MP change + // (and not an app deploy). + return await info.mergeInfo.delegateToSchema({ + schema: kawsSchema, + operation: "query", + fieldName: "marketingCollections", + args: { + slugs: [ + "new-this-week", + "auction-highlights", + "trending-emerging-artists", + ], + }, + context, + info, + }) + } catch (error) { + // The schema guarantees a present array for results, so fall back + // to an empty one if the request to kaws fails. Note that we + // still bubble-up any errors in the GraphQL response. + return [] + } + }, + }, + }, + Viewer: { + marketingCollections: { + fragment: gql` + ...on Viewer { + __typename + } + `, + resolve: async (_source, args, context, info) => { + return await info.mergeInfo.delegateToSchema({ + schema: kawsSchema, + operation: "query", + fieldName: "marketingCollections", + + args, + context, + info, + }) + }, + }, + }, + MarketingCollection: { + artworksConnection: { + fragment: ` + fragment MarketingCollectionQuery on MarketingCollection { + query { + ${Object.keys(filterArtworksArgs).join("\n")} + } + } + `, + resolve: (parent, _args, context, info) => { + const query = parent.query + const hasKeyword = Boolean(parent.query.keyword) + + const existingLoader = + context.unauthenticatedLoaders.filterArtworksLoader + const newLoader = (loaderParams) => { + return existingLoader.call(null, loaderParams, { + requestThrottleMs: 1000 * 60 * 60, + }) + } + + // TODO: Should this really modify the context in place? + context.unauthenticatedLoaders.filterArtworksLoader = newLoader + + return info.mergeInfo.delegateToSchema({ + schema: localSchema, + operation: "query", + fieldName: "artworksConnection", + args: { + ...query, + keywordMatchExact: hasKeyword, + ..._args, + }, + context, + info, + }) + }, + }, + internalID: { + fragment: ` + fragment MarketingCollectionIDQuery on MarketingCollection { + id + } + `, + resolve: ({ id }, _args, _context, _info) => id, + }, + }, + }, + } +} + +// Very contrived version of what exists in graphql-js but isn’t exported. +// https://github.com/graphql/graphql-js/blob/master/src/utilities/schemaPrinter.js +function argsToSDL(args: GraphQLFieldConfigArgumentMap) { + const result: string[] = [] + Object.keys(args).forEach((argName) => { + result.push(`${argName}: ${printType(args[argName].type)}`) + }) + return result +} diff --git a/src/lib/stitching2/lib/createRemoteExecutor.ts b/src/lib/stitching2/lib/createRemoteExecutor.ts new file mode 100644 index 0000000000..9f3617188e --- /dev/null +++ b/src/lib/stitching2/lib/createRemoteExecutor.ts @@ -0,0 +1,66 @@ +import fetch from "node-fetch" +import { print } from "graphql" +import { ExecutionParams, Executor } from "@graphql-tools/delegate" +import { ResolverContext } from "types/graphql" + +/** + * The parameter that's passed down to an executor's middleware + */ +interface ExecutorMiddlewareOperationParameter + extends ExecutionParams { + /** The operation's parsed result payload */ + result: unknown + /** A stringified representation of the operation */ + text: string +} + +export type ExecutorMiddleware = ( + operation: ExecutorMiddlewareOperationParameter +) => ExecutorMiddlewareOperationParameter + +interface ExecutorOptions { + /** Middleware runs at the end of the operation execution */ + middleware?: ExecutorMiddleware[] +} + +/** + * + * @param graphqlURI URI to the remote graphql service + * @param options Object used to specify middleware or other configuration for the executor + */ +export const createRemoteExecutor = ( + graphqlURI: string, + options: ExecutorOptions = {} +) => { + const { middleware = [] } = options + + return async ({ + document, + variables, + ...otherOptions + }): Promise => { + const query = print(document) + const fetchResult = await fetch(graphqlURI, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ query, variables }), + }) + const result = await fetchResult.json() + if (middleware.length) { + return middleware.reduce( + (acc, middleware) => + middleware({ + document, + variables, + text: query, + result: acc, + ...otherOptions, + }), + result + ).result + } + return result + } +} diff --git a/src/lib/stitching2/mergeSchemas.ts b/src/lib/stitching2/mergeSchemas.ts new file mode 100644 index 0000000000..398d8d3c27 --- /dev/null +++ b/src/lib/stitching2/mergeSchemas.ts @@ -0,0 +1,41 @@ +import { GraphQLSchema } from "graphql" +import { executableKawsSchema } from "./kaws/schema" +import { kawsStitchingEnvironmentV2 } from "./kaws/v2/stitching" + +const { stitchSchemas } = require("@graphql-tools/stitch") + +export const incrementalMergeSchemas2 = async (localSchema) => { + const subschemas = [localSchema] as GraphQLSchema[] + const extensionResolvers = {} as any + const extensionSchemas = [] as string[] + + const useStitchingEnvironment = ({ extensionSchema, resolvers }) => { + extensionSchemas.push(extensionSchema) + for (const [type, fieldResolvers] of Object.entries( + resolvers as Record> + )) { + extensionResolvers[type] = { + ...extensionResolvers[type], + ...fieldResolvers, + } + } + + // debugger + } + + const kawsSchema = await executableKawsSchema() + subschemas.push(kawsSchema.schema) + useStitchingEnvironment( + kawsStitchingEnvironmentV2(localSchema, kawsSchema.schema) + ) + + const stitchedSchemas = stitchSchemas({ + subschemas, + resolvers: extensionResolvers, + typeDefs: extensionSchemas, + }) + + // debugger + + return stitchedSchemas +} diff --git a/src/lib/stitching2/middleware/responseLoggerMiddleware.ts b/src/lib/stitching2/middleware/responseLoggerMiddleware.ts new file mode 100644 index 0000000000..acb36a1ee8 --- /dev/null +++ b/src/lib/stitching2/middleware/responseLoggerMiddleware.ts @@ -0,0 +1,29 @@ +import { ExecutorMiddleware } from "lib/stitching2/lib/createRemoteExecutor" +import extensionsLogger from "lib/loaders/api/extensionsLogger" +import config from "config" + +const shouldLogLinkTraffic = + !!process.env.LOG_HTTP_LINKS && typeof jest === "undefined" +const { ENABLE_REQUEST_LOGGING } = config +const enableRequestLogging = ENABLE_REQUEST_LOGGING === "true" + +export const responseLoggerMiddleware = (name: string): ExecutorMiddleware => { + return (operation) => { + if (shouldLogLinkTraffic) { + console.log(`>\n> Made query to ${name}:`) + console.log(">\n" + operation.text) + console.log(`> Got Response:`) + console.log("> " + JSON.stringify(operation.result)) + } + if (enableRequestLogging) { + const requestID = operation.context?.requestIDs.requestID + if (requestID) { + extensionsLogger(requestID, "stitching", name.toLowerCase(), { + query: operation.text, + vars: operation.variables, + }) + } + } + return operation + } +} diff --git a/src/schema/v2/index.ts b/src/schema/v2/index.ts index 11e61baa04..1de3f534b5 100644 --- a/src/schema/v2/index.ts +++ b/src/schema/v2/index.ts @@ -1,24 +1,47 @@ import localSchema from "./schema" import { incrementalMergeSchemas } from "lib/stitching/mergeSchemas" +import { incrementalMergeSchemas2 } from "lib/stitching2/mergeSchemas" import { lexicographicSortSchema } from "graphql" - import config from "config" -const { DISABLE_SCHEMA_STITCHING } = config + +const { + DISABLE_SCHEMA_STITCHING, + ENABLE_EXPERIMENTAL_STITCHING_MIGRATION, +} = config // Default to the existing metaphysics schema let exportedSchema = localSchema -// If DISABLE_SCHEMA_STITCHING is set in the env -// then don't stitch -const enableSchemaStitching = !DISABLE_SCHEMA_STITCHING -if (enableSchemaStitching) { - try { - if (typeof jest == "undefined") { - console.warn("[V2] [FEATURE] Enabling Schema Stitching") + +export async function getSchema() { + const enableSchemaStitching = !DISABLE_SCHEMA_STITCHING + if (enableSchemaStitching) { + try { + if (typeof jest == "undefined") { + console.warn("[V2] [FEATURE] Enabling Schema Stitching") + } + exportedSchema = incrementalMergeSchemas(exportedSchema, 2) + } catch (err) { + console.log("[V2] Error merging schemas:", err) } - exportedSchema = incrementalMergeSchemas(exportedSchema, 2) - } catch (err) { - console.log("[V2] Error merging schemas:", err) } -} -export const schema = lexicographicSortSchema(exportedSchema) + // TODO: Remove this flag once stitching lib is upgraded + if (ENABLE_EXPERIMENTAL_STITCHING_MIGRATION) { + try { + if (typeof jest == "undefined") { + console.warn( + "[V2] [ENABLE_EXPERIMENTAL_STITCHING_MIGRATION] Enabling experimental Schema Stitching migration" + ) + } + exportedSchema = await incrementalMergeSchemas2(exportedSchema, 2) + } catch (err) { + console.log( + "[V2] [ENABLE_EXPERIMENTAL_STITCHING_MIGRATION] Error merging schemas:", + err + ) + } + } + + const schema = lexicographicSortSchema(exportedSchema) + return schema +} diff --git a/yarn.lock b/yarn.lock index be40ed1fbf..509a424e78 100644 --- a/yarn.lock +++ b/yarn.lock @@ -971,6 +971,26 @@ dependencies: dependency-graph "0.8.1" +"@graphql-tools/batch-delegate@8.0.12": + version "8.0.12" + resolved "https://registry.yarnpkg.com/@graphql-tools/batch-delegate/-/batch-delegate-8.0.12.tgz#77089a6ff5ea4c31c7612e5555418fa3cf2e9146" + integrity sha512-ThqBdrL4dMSTKPLK7XHBg0Uv1JmqiL/oWEQ6/PLiTz6llwNzcK5s1CTTRgerwvRjCLyXiQnidMpdVQADp0jCQg== + dependencies: + "@graphql-tools/delegate" "^8.1.1" + "@graphql-tools/utils" "^8.1.2" + dataloader "2.0.0" + tslib "~2.3.0" + +"@graphql-tools/batch-execute@^8.0.5": + version "8.0.5" + resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-8.0.5.tgz#a0f8a9ff2c61209974c626faf3dd922a5c68d2b0" + integrity sha512-Zx+zs12BLGNvrQtfESIhitzwIkrWnKyKOkAfcaMNuOLGOO2pDmhwIRzbHj+6Jtq9V1/JTaVkSnm/4ozaCRck5A== + dependencies: + "@graphql-tools/utils" "^8.1.1" + dataloader "2.0.0" + tslib "~2.3.0" + value-or-promise "1.0.10" + "@graphql-tools/delegate@6.0.10": version "6.0.10" resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-6.0.10.tgz#f2fe8eea6cd5ce23f1e8f3dacfa6e136cad157da" @@ -981,6 +1001,55 @@ aggregate-error "3.0.1" tslib "~2.0.0" +"@graphql-tools/delegate@^8.1.0", "@graphql-tools/delegate@^8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-8.1.1.tgz#d20e6d81a2900b1c8a69c2c0a3a8a0df2f9030c2" + integrity sha512-Vttd0nfYTqRnRMKLvk8s4cIi9U+OMXGc9CMZAlKkHrBJ6dGXjdSM+4n3p9rfWZc/FtbVk1FnNS4IFyMeKwFuxA== + dependencies: + "@graphql-tools/batch-execute" "^8.0.5" + "@graphql-tools/schema" "^8.1.2" + "@graphql-tools/utils" "^8.1.2" + dataloader "2.0.0" + tslib "~2.3.0" + value-or-promise "1.0.10" + +"@graphql-tools/graphql-file-loader@^7.0.6": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-file-loader/-/graphql-file-loader-7.0.6.tgz#602a2013dc926e17542c979b8f9af45187329bcb" + integrity sha512-jndtcNwPUQxEiY/3FKNbAb4dpNXO8tXoDZzrnvv+z/tf27ViiZW0KUBkO4Mw4b0sqaDq+fS4d6BXzVFQQUPolA== + dependencies: + "@graphql-tools/import" "^6.2.6" + "@graphql-tools/utils" "^8.1.2" + globby "^11.0.3" + tslib "~2.3.0" + unixify "^1.0.0" + +"@graphql-tools/import@^6.2.6": + version "6.3.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/import/-/import-6.3.1.tgz#731c47ab6c6ac9f7994d75c76b6c2fa127d2d483" + integrity sha512-1szR19JI6WPibjYurMLdadHKZoG9C//8I/FZ0Dt4vJSbrMdVNp8WFxg4QnZrDeMG4MzZc90etsyF5ofKjcC+jw== + dependencies: + resolve-from "5.0.0" + tslib "~2.2.0" + +"@graphql-tools/load@^7.1.9": + version "7.1.9" + resolved "https://registry.yarnpkg.com/@graphql-tools/load/-/load-7.1.9.tgz#6bcff0a2866051ecdf514e6a8f82c2b4c0f5401d" + integrity sha512-4R0JLXRynPgHRWkGvL778XNH3IYX1sXjmEqGy3LPpJ4KR6woCO0us8oXNMAJMjjU4ZcOX6I8Jdj16G7qcHYTLA== + dependencies: + "@graphql-tools/schema" "8.1.2" + "@graphql-tools/utils" "^8.1.2" + p-limit "3.1.0" + tslib "~2.3.0" + +"@graphql-tools/merge@^8.0.2", "@graphql-tools/merge@^8.0.3": + version "8.0.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.0.3.tgz#56c844bc5d7d833456695c8e5eda4f1a0d5be873" + integrity sha512-lVMyW9cREs+nQYbUvMaaqSl+pRCezl2RafNMFi/04akjvOtjVefdi7n3pArpSqPhLHPJDyQRlI8CK8cmOZ9jTA== + dependencies: + "@graphql-tools/utils" "^8.1.2" + tslib "~2.3.0" + "@graphql-tools/schema@6.0.10": version "6.0.10" resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-6.0.10.tgz#69b36fad35ea5780f8539c92e776f9e83d929575" @@ -989,6 +1058,29 @@ "@graphql-tools/utils" "6.0.10" tslib "~2.0.0" +"@graphql-tools/schema@8.1.2", "@graphql-tools/schema@^8.1.2": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-8.1.2.tgz#913879da1a7889a9488e9b7dc189e7c83eff74be" + integrity sha512-rX2pg42a0w7JLVYT+f/yeEKpnoZL5PpLq68TxC3iZ8slnNBNjfVfvzzOn8Q8Q6Xw3t17KP9QespmJEDfuQe4Rg== + dependencies: + "@graphql-tools/merge" "^8.0.2" + "@graphql-tools/utils" "^8.1.1" + tslib "~2.3.0" + value-or-promise "1.0.10" + +"@graphql-tools/stitch@^8.2.1": + version "8.2.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/stitch/-/stitch-8.2.1.tgz#19f174e642b6e4ae16064215706acd59d71f6520" + integrity sha512-QZ4qu++9XwrSVL51DpmwRSpPkdS7ScbyTkHOtudAwQv/rti6RP+qlAaRwMLao1WZfjZDnNJj/JeXqnPHjHTj8w== + dependencies: + "@graphql-tools/batch-delegate" "8.0.12" + "@graphql-tools/delegate" "^8.1.1" + "@graphql-tools/merge" "^8.0.3" + "@graphql-tools/schema" "^8.1.2" + "@graphql-tools/utils" "^8.1.2" + "@graphql-tools/wrap" "^8.0.13" + tslib "~2.3.0" + "@graphql-tools/utils@6.0.10": version "6.0.10" resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-6.0.10.tgz#ed15110a20acc5474a8dda5c0b99f970ba696c75" @@ -997,6 +1089,24 @@ aggregate-error "3.0.1" camel-case "4.1.1" +"@graphql-tools/utils@^8.1.1", "@graphql-tools/utils@^8.1.2": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.1.2.tgz#a376259fafbca7532fda657e3abeec23b545e5d3" + integrity sha512-3G+NIBR5mHjPm78jAD0l07JRE0XH+lr9m7yL/wl69jAzK0Jr/H+/Ok4ljEolI70iglz+ZhIShVPAwyesF6rnFg== + dependencies: + tslib "~2.3.0" + +"@graphql-tools/wrap@^8.0.13": + version "8.0.13" + resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-8.0.13.tgz#17a4096efbc64e15b27a74135d920c8bd3e5385a" + integrity sha512-GTkHbN+Zgs+D7bFniFx3/YqNIDv8ET17prM7FewmU8LNRc2P48y6d4/dkQLcwQmryy1TZF87es6yA9FMNfQtWg== + dependencies: + "@graphql-tools/delegate" "^8.1.0" + "@graphql-tools/schema" "^8.1.2" + "@graphql-tools/utils" "^8.1.1" + tslib "~2.3.0" + value-or-promise "1.0.10" + "@heroku/foreman@2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@heroku/foreman/-/foreman-2.0.2.tgz#e24f8611bb0633ca89095648243d3a90564749fc" @@ -3428,6 +3538,11 @@ dataloader@1.3.0: resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-1.3.0.tgz#6fec5be4b30a712e4afd30b86b4334566b97673b" integrity sha1-b+xb5LMKcS5K/TC4a0M0VmuXZzs= +dataloader@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dataloader/-/dataloader-2.0.0.tgz#41eaf123db115987e21ca93c005cd7753c55fe6f" + integrity sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ== + date-fns@^1.27.2: version "1.29.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" @@ -4837,6 +4952,18 @@ globby@^11.0.1: merge2 "^1.3.0" slash "^3.0.0" +globby@^11.0.3: + version "11.0.4" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" + integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + globrex@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098" @@ -7841,6 +7968,13 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= +p-limit@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + p-limit@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" @@ -8859,6 +8993,11 @@ resolve-cwd@^2.0.0: dependencies: resolve-from "^3.0.0" +resolve-from@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" @@ -9926,6 +10065,16 @@ tslib@~2.0.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== +tslib@~2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" + integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== + +tslib@~2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + tsutils@^3.17.1: version "3.17.1" resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" @@ -10057,6 +10206,13 @@ universalify@^0.1.0: resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== +unixify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090" + integrity sha1-OmQcjC/7zk2mg6XHDwOkYpQMIJA= + dependencies: + normalize-path "^2.1.1" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" @@ -10172,6 +10328,11 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" +value-or-promise@1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.10.tgz#5bf041f1e9a8e7043911875547636768a836e446" + integrity sha512-1OwTzvcfXkAfabk60UVr5NdjtjJ0Fg0T5+B1bhxtrOEwSH2fe8y4DnLgoksfCyd8yZCOQQHB0qLMQnwgCjbXLQ== + vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -10413,6 +10574,11 @@ yargs@^13.3.0: y18n "^4.0.0" yargs-parser "^13.1.1" +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + zen-observable-ts@^0.8.19: version "0.8.19" resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.19.tgz#c094cd20e83ddb02a11144a6e2a89706946b5694" From bbe5d60811910987b52f6973fc32a3f58efd87fe Mon Sep 17 00:00:00 2001 From: Christopher Pappas Date: Mon, 30 Aug 2021 17:41:35 -0700 Subject: [PATCH 2/6] wip --- src/index.ts | 4 ++-- src/lib/stitching2/kaws/v2/stitching.ts | 12 ++++-------- src/lib/stitching2/mergeSchemas.ts | 15 +++++++++------ 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/index.ts b/src/index.ts index 05e2ec11cf..24adfe86f9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -271,8 +271,8 @@ const app = express() try { const schemaV2 = await getSchemaV2() // This order is important for dd-trace to be able to find the nested routes. - app.use("/v2", (req, res, next) => startApp(schemaV2, "/")(req, res, next)) - app.use("/", (req, res, next) => startApp(schemaV1, "/")(req, res, next)) + app.use("/v2", startApp(schemaV2, "/")) + app.use("/", startApp(schemaV1, "/")) } catch (error) { console.log(error) } diff --git a/src/lib/stitching2/kaws/v2/stitching.ts b/src/lib/stitching2/kaws/v2/stitching.ts index c0d2f39e7c..346e0a1bcc 100644 --- a/src/lib/stitching2/kaws/v2/stitching.ts +++ b/src/lib/stitching2/kaws/v2/stitching.ts @@ -5,6 +5,7 @@ import { } from "schema/v2/filterArtworksConnection" import gql from "lib/gql" import { printType } from "lib/stitching/lib/printType" +import { delegateToSchema } from "@graphql-tools/delegate" export const kawsStitchingEnvironmentV2 = ( localSchema: GraphQLSchema, @@ -41,17 +42,12 @@ export const kawsStitchingEnvironmentV2 = ( resolvers: { Artist: { marketingCollections: { - fragment: ` - ... on Artist { - internalID - } - `, + selectionSet: `{ internalID }`, resolve: ({ internalID: artistID }, args, context, info) => { - return info.mergeInfo.delegateToSchema({ + return delegateToSchema({ schema: kawsSchema, operation: "query", fieldName: "marketingCollections", - args: { artistID, ...args, @@ -71,7 +67,7 @@ export const kawsStitchingEnvironmentV2 = ( `, resolve: ({ kawsCollectionSlugs: slugs }, args, context, info) => { if (slugs.length === 0) return [] - return info.mergeInfo.delegateToSchema({ + return info.stitchingInfo.delegateToSchema({ schema: kawsSchema, operation: "query", fieldName: "marketingCollections", diff --git a/src/lib/stitching2/mergeSchemas.ts b/src/lib/stitching2/mergeSchemas.ts index 398d8d3c27..6ebc8dcc93 100644 --- a/src/lib/stitching2/mergeSchemas.ts +++ b/src/lib/stitching2/mergeSchemas.ts @@ -24,18 +24,21 @@ export const incrementalMergeSchemas2 = async (localSchema) => { } const kawsSchema = await executableKawsSchema() - subschemas.push(kawsSchema.schema) - useStitchingEnvironment( - kawsStitchingEnvironmentV2(localSchema, kawsSchema.schema) - ) + subschemas.push(kawsSchema) + useStitchingEnvironment(kawsStitchingEnvironmentV2(localSchema, kawsSchema)) - const stitchedSchemas = stitchSchemas({ + const stitchedSchema = stitchSchemas({ subschemas, resolvers: extensionResolvers, typeDefs: extensionSchemas, }) + // Because __allowedLegacyNames isn't in the public API + Object.defineProperty(stitchedSchema, "__allowedLegacyNames", { + value: ["__id"], + }) + // debugger - return stitchedSchemas + return stitchedSchema } From 4a6fbee6c2b0b5c181f55c4621000d10dcc121ea Mon Sep 17 00:00:00 2001 From: Christopher Pappas Date: Tue, 28 Sep 2021 11:39:08 -0700 Subject: [PATCH 3/6] fix stitching logging --- src/config.ts | 2 ++ src/lib/stitching2/kaws/v2/stitching.ts | 13 +++++++------ .../middleware/responseLoggerMiddleware.ts | 6 ++++-- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/config.ts b/src/config.ts index 9fb08f18f4..f930f46fda 100644 --- a/src/config.ts +++ b/src/config.ts @@ -62,6 +62,7 @@ const { IMPULSE_APPLICATION_ID, INTROSPECT_TOKEN, IP_BLACKLIST, + LOG_HTTP_LINKS, LOG_QUERY_DETAILS_THRESHOLD, MEMCACHED_MAX_POOL, MEMCACHED_URL, @@ -193,6 +194,7 @@ export default { IMPULSE_APPLICATION_ID, INTROSPECT_TOKEN, IP_BLACKLIST: IP_BLACKLIST || "", + LOG_HTTP_LINKS, LOG_QUERY_DETAILS_THRESHOLD, MEMCACHED_MAX_POOL: Number(MEMCACHED_MAX_POOL) || 10, MEMCACHED_URL: MEMCACHED_URL || "localhost:11211", diff --git a/src/lib/stitching2/kaws/v2/stitching.ts b/src/lib/stitching2/kaws/v2/stitching.ts index 346e0a1bcc..7276726677 100644 --- a/src/lib/stitching2/kaws/v2/stitching.ts +++ b/src/lib/stitching2/kaws/v2/stitching.ts @@ -44,6 +44,7 @@ export const kawsStitchingEnvironmentV2 = ( marketingCollections: { selectionSet: `{ internalID }`, resolve: ({ internalID: artistID }, args, context, info) => { + console.log("************************* resolving here!") return delegateToSchema({ schema: kawsSchema, operation: "query", @@ -152,12 +153,12 @@ export const kawsStitchingEnvironmentV2 = ( MarketingCollection: { artworksConnection: { fragment: ` - fragment MarketingCollectionQuery on MarketingCollection { - query { - ${Object.keys(filterArtworksArgs).join("\n")} - } - } - `, + fragment MarketingCollectionQuery on MarketingCollection { + query { + ${Object.keys(filterArtworksArgs).join("\n")} + } + } + `, resolve: (parent, _args, context, info) => { const query = parent.query const hasKeyword = Boolean(parent.query.keyword) diff --git a/src/lib/stitching2/middleware/responseLoggerMiddleware.ts b/src/lib/stitching2/middleware/responseLoggerMiddleware.ts index acb36a1ee8..e8028709b9 100644 --- a/src/lib/stitching2/middleware/responseLoggerMiddleware.ts +++ b/src/lib/stitching2/middleware/responseLoggerMiddleware.ts @@ -2,9 +2,11 @@ import { ExecutorMiddleware } from "lib/stitching2/lib/createRemoteExecutor" import extensionsLogger from "lib/loaders/api/extensionsLogger" import config from "config" +const { ENABLE_REQUEST_LOGGING, LOG_HTTP_LINKS } = config + const shouldLogLinkTraffic = - !!process.env.LOG_HTTP_LINKS && typeof jest === "undefined" -const { ENABLE_REQUEST_LOGGING } = config + LOG_HTTP_LINKS === "true" && typeof jest === "undefined" + const enableRequestLogging = ENABLE_REQUEST_LOGGING === "true" export const responseLoggerMiddleware = (name: string): ExecutorMiddleware => { From 9d21a4613259cee94888d1825997e552c936e60a Mon Sep 17 00:00:00 2001 From: Christopher Pappas Date: Tue, 28 Sep 2021 11:51:41 -0700 Subject: [PATCH 4/6] fix --- src/lib/stitching2/kaws/v2/stitching.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/stitching2/kaws/v2/stitching.ts b/src/lib/stitching2/kaws/v2/stitching.ts index 7276726677..439fef80a5 100644 --- a/src/lib/stitching2/kaws/v2/stitching.ts +++ b/src/lib/stitching2/kaws/v2/stitching.ts @@ -44,7 +44,7 @@ export const kawsStitchingEnvironmentV2 = ( marketingCollections: { selectionSet: `{ internalID }`, resolve: ({ internalID: artistID }, args, context, info) => { - console.log("************************* resolving here!") + debugger return delegateToSchema({ schema: kawsSchema, operation: "query", From 8ed8ecf6297ac4ca6e1340acbf5900f00f053138 Mon Sep 17 00:00:00 2001 From: Christopher Pappas Date: Wed, 15 Dec 2021 21:59:56 -0800 Subject: [PATCH 5/6] progress --- package.json | 12 +- src/lib/stitching2/kaws/v2/stitching.ts | 66 ++++--- yarn.lock | 249 ++++++++---------------- 3 files changed, 123 insertions(+), 204 deletions(-) diff --git a/package.json b/package.json index c4015106b5..11fb130f09 100644 --- a/package.json +++ b/package.json @@ -48,12 +48,12 @@ "@babel/preset-env": "7.4.5", "@babel/preset-typescript": "7.3.3", "@babel/register": "7.4.4", - "@graphql-tools/delegate": "6.0.10", - "@graphql-tools/graphql-file-loader": "^7.0.6", - "@graphql-tools/load": "^7.1.9", - "@graphql-tools/schema": "^8.1.2", - "@graphql-tools/stitch": "^8.2.1", - "@graphql-tools/wrap": "^8.0.13", + "@graphql-tools/delegate": "^8.4.3", + "@graphql-tools/graphql-file-loader": "^7.3.3", + "@graphql-tools/load": "^7.5.0", + "@graphql-tools/schema": "^8.3.1", + "@graphql-tools/stitch": "^8.4.3", + "@graphql-tools/wrap": "^8.3.2", "@heroku/foreman": "2.0.2", "@sentry/node": "5.18.1", "accounting": "0.4.1", diff --git a/src/lib/stitching2/kaws/v2/stitching.ts b/src/lib/stitching2/kaws/v2/stitching.ts index 439fef80a5..acb6dd45b5 100644 --- a/src/lib/stitching2/kaws/v2/stitching.ts +++ b/src/lib/stitching2/kaws/v2/stitching.ts @@ -44,7 +44,6 @@ export const kawsStitchingEnvironmentV2 = ( marketingCollections: { selectionSet: `{ internalID }`, resolve: ({ internalID: artistID }, args, context, info) => { - debugger return delegateToSchema({ schema: kawsSchema, operation: "query", @@ -61,14 +60,16 @@ export const kawsStitchingEnvironmentV2 = ( }, Fair: { marketingCollections: { - fragment: ` - ... on Fair { - kawsCollectionSlugs - } - `, + selectionSet: gql` + { + ... on Fair { + kawsCollectionSlugs + } + } + `, resolve: ({ kawsCollectionSlugs: slugs }, args, context, info) => { if (slugs.length === 0) return [] - return info.stitchingInfo.delegateToSchema({ + return delegateToSchema({ schema: kawsSchema, operation: "query", fieldName: "marketingCollections", @@ -85,11 +86,13 @@ export const kawsStitchingEnvironmentV2 = ( }, HomePage: { marketingCollectionsModule: { - fragment: gql` + selectionSet: gql` + { ... on HomePage { __typename } - `, + } + `, resolve: () => { return {} }, @@ -97,9 +100,11 @@ export const kawsStitchingEnvironmentV2 = ( }, HomePageMarketingCollectionsModule: { results: { - fragment: gql` - ... on HomePageMarketingCollectionsModule { - __typename + selectionSet: gql` + { + ... on HomePageMarketingCollectionsModule { + __typename + } } `, resolve: async (_source, _args, context, info) => { @@ -107,7 +112,7 @@ export const kawsStitchingEnvironmentV2 = ( // We hard-code the collections slugs here in MP so that the app // can display different collections based only on an MP change // (and not an app deploy). - return await info.mergeInfo.delegateToSchema({ + return delegateToSchema({ schema: kawsSchema, operation: "query", fieldName: "marketingCollections", @@ -132,17 +137,18 @@ export const kawsStitchingEnvironmentV2 = ( }, Viewer: { marketingCollections: { - fragment: gql` - ...on Viewer { - __typename + selectionSet: gql` + { + ... on Viewer { + __typename + } } `, resolve: async (_source, args, context, info) => { - return await info.mergeInfo.delegateToSchema({ + return delegateToSchema({ schema: kawsSchema, operation: "query", fieldName: "marketingCollections", - args, context, info, @@ -152,16 +158,16 @@ export const kawsStitchingEnvironmentV2 = ( }, MarketingCollection: { artworksConnection: { - fragment: ` + selectionSet: gql` fragment MarketingCollectionQuery on MarketingCollection { query { ${Object.keys(filterArtworksArgs).join("\n")} } } `, - resolve: (parent, _args, context, info) => { + resolve: (parent, args, context, info) => { const query = parent.query - const hasKeyword = Boolean(parent.query.keyword) + const hasKeyword = Boolean(args.keyword) const existingLoader = context.unauthenticatedLoaders.filterArtworksLoader @@ -174,14 +180,14 @@ export const kawsStitchingEnvironmentV2 = ( // TODO: Should this really modify the context in place? context.unauthenticatedLoaders.filterArtworksLoader = newLoader - return info.mergeInfo.delegateToSchema({ + return delegateToSchema({ schema: localSchema, operation: "query", fieldName: "artworksConnection", args: { ...query, keywordMatchExact: hasKeyword, - ..._args, + ...args, }, context, info, @@ -189,12 +195,14 @@ export const kawsStitchingEnvironmentV2 = ( }, }, internalID: { - fragment: ` - fragment MarketingCollectionIDQuery on MarketingCollection { - id - } - `, - resolve: ({ id }, _args, _context, _info) => id, + selectionSet: gql` + fragment MarketingCollectionIDQuery on MarketingCollection { + id + } + `, + resolve: ({ id }, _args, _context, _info) => { + return id + }, }, }, }, diff --git a/yarn.lock b/yarn.lock index 509a424e78..b800accd77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -971,141 +971,116 @@ dependencies: dependency-graph "0.8.1" -"@graphql-tools/batch-delegate@8.0.12": - version "8.0.12" - resolved "https://registry.yarnpkg.com/@graphql-tools/batch-delegate/-/batch-delegate-8.0.12.tgz#77089a6ff5ea4c31c7612e5555418fa3cf2e9146" - integrity sha512-ThqBdrL4dMSTKPLK7XHBg0Uv1JmqiL/oWEQ6/PLiTz6llwNzcK5s1CTTRgerwvRjCLyXiQnidMpdVQADp0jCQg== +"@graphql-tools/batch-delegate@8.2.3": + version "8.2.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/batch-delegate/-/batch-delegate-8.2.3.tgz#5651a9e5283d42088141337d24d9bb8798d87121" + integrity sha512-0205ujghXof7ZsKuBkhGJgie46ZKV4BSShWD4HI4H2O+5WSVzR/n5+jAl/KIMmJ9HomwxfXlYYfBHWTcIQ8s7g== dependencies: - "@graphql-tools/delegate" "^8.1.1" - "@graphql-tools/utils" "^8.1.2" + "@graphql-tools/delegate" "^8.4.3" + "@graphql-tools/utils" "^8.5.4" dataloader "2.0.0" tslib "~2.3.0" -"@graphql-tools/batch-execute@^8.0.5": - version "8.0.5" - resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-8.0.5.tgz#a0f8a9ff2c61209974c626faf3dd922a5c68d2b0" - integrity sha512-Zx+zs12BLGNvrQtfESIhitzwIkrWnKyKOkAfcaMNuOLGOO2pDmhwIRzbHj+6Jtq9V1/JTaVkSnm/4ozaCRck5A== +"@graphql-tools/batch-execute@^8.3.1": + version "8.3.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-8.3.1.tgz#0b74c54db5ac1c5b9a273baefc034c2343ebbb74" + integrity sha512-63kHY8ZdoO5FoeDXYHnAak1R3ysMViMPwWC2XUblFckuVLMUPmB2ONje8rjr2CvzWBHAW8c1Zsex+U3xhKtGIA== dependencies: - "@graphql-tools/utils" "^8.1.1" + "@graphql-tools/utils" "^8.5.1" dataloader "2.0.0" tslib "~2.3.0" - value-or-promise "1.0.10" - -"@graphql-tools/delegate@6.0.10": - version "6.0.10" - resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-6.0.10.tgz#f2fe8eea6cd5ce23f1e8f3dacfa6e136cad157da" - integrity sha512-FBHrmpSI9QpNbvqc5D4wdQW0WrNVUA2ylFhzsNRk9yvlKzcVKqiTrOpb++j7TLB+tG06dpSkfAssPcgZvU60fw== - dependencies: - "@graphql-tools/schema" "6.0.10" - "@graphql-tools/utils" "6.0.10" - aggregate-error "3.0.1" - tslib "~2.0.0" - -"@graphql-tools/delegate@^8.1.0", "@graphql-tools/delegate@^8.1.1": - version "8.1.1" - resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-8.1.1.tgz#d20e6d81a2900b1c8a69c2c0a3a8a0df2f9030c2" - integrity sha512-Vttd0nfYTqRnRMKLvk8s4cIi9U+OMXGc9CMZAlKkHrBJ6dGXjdSM+4n3p9rfWZc/FtbVk1FnNS4IFyMeKwFuxA== - dependencies: - "@graphql-tools/batch-execute" "^8.0.5" - "@graphql-tools/schema" "^8.1.2" - "@graphql-tools/utils" "^8.1.2" + value-or-promise "1.0.11" + +"@graphql-tools/delegate@^8.4.2", "@graphql-tools/delegate@^8.4.3": + version "8.4.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-8.4.3.tgz#ad73ed7cc3b4cad9242c6d4835a5ae0b640f7164" + integrity sha512-hKTJdJXJnKL0+2vpU+Kt7OHQTIXZ9mBmNBwHsYiG5WNArz/vNI7910r6TC2XMf/e7zhyyK+mXxMDBmDQkkJagA== + dependencies: + "@graphql-tools/batch-execute" "^8.3.1" + "@graphql-tools/schema" "^8.3.1" + "@graphql-tools/utils" "^8.5.4" dataloader "2.0.0" tslib "~2.3.0" - value-or-promise "1.0.10" + value-or-promise "1.0.11" -"@graphql-tools/graphql-file-loader@^7.0.6": - version "7.0.6" - resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-file-loader/-/graphql-file-loader-7.0.6.tgz#602a2013dc926e17542c979b8f9af45187329bcb" - integrity sha512-jndtcNwPUQxEiY/3FKNbAb4dpNXO8tXoDZzrnvv+z/tf27ViiZW0KUBkO4Mw4b0sqaDq+fS4d6BXzVFQQUPolA== +"@graphql-tools/graphql-file-loader@^7.3.3": + version "7.3.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/graphql-file-loader/-/graphql-file-loader-7.3.3.tgz#7cee2f84f08dc13fa756820b510248b857583d36" + integrity sha512-6kUJZiNpYKVhum9E5wfl5PyLLupEDYdH7c8l6oMrk6c7EPEVs6iSUyB7yQoWrtJccJLULBW2CRQ5IHp5JYK0mA== dependencies: - "@graphql-tools/import" "^6.2.6" - "@graphql-tools/utils" "^8.1.2" + "@graphql-tools/import" "^6.5.7" + "@graphql-tools/utils" "^8.5.1" globby "^11.0.3" tslib "~2.3.0" unixify "^1.0.0" -"@graphql-tools/import@^6.2.6": - version "6.3.1" - resolved "https://registry.yarnpkg.com/@graphql-tools/import/-/import-6.3.1.tgz#731c47ab6c6ac9f7994d75c76b6c2fa127d2d483" - integrity sha512-1szR19JI6WPibjYurMLdadHKZoG9C//8I/FZ0Dt4vJSbrMdVNp8WFxg4QnZrDeMG4MzZc90etsyF5ofKjcC+jw== +"@graphql-tools/import@^6.5.7": + version "6.6.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/import/-/import-6.6.3.tgz#e2983d9623d4abd7a5ef2f65f7cc8ff745a1a691" + integrity sha512-k/QkWCZ5rPVgFw1eE4GXPXltw9/mEiJj6F6bJvFKJr1C6im8Y60pl0Pv+SByGZQGuukXE0uR16Mv4OFGSMQIaQ== dependencies: + "@graphql-tools/utils" "8.5.5" resolve-from "5.0.0" - tslib "~2.2.0" + tslib "~2.3.0" -"@graphql-tools/load@^7.1.9": - version "7.1.9" - resolved "https://registry.yarnpkg.com/@graphql-tools/load/-/load-7.1.9.tgz#6bcff0a2866051ecdf514e6a8f82c2b4c0f5401d" - integrity sha512-4R0JLXRynPgHRWkGvL778XNH3IYX1sXjmEqGy3LPpJ4KR6woCO0us8oXNMAJMjjU4ZcOX6I8Jdj16G7qcHYTLA== +"@graphql-tools/load@^7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@graphql-tools/load/-/load-7.5.0.tgz#cede03b1222a01c55f5e8a85f099444cf0a98785" + integrity sha512-f0k12xZzxfV4BxWyvt/f8opqICXvz4WzDrVVG4udHFgUJIjhGeE67SRTWFAK/jlIp4QgaDux7L1DXQkJnmx64w== dependencies: - "@graphql-tools/schema" "8.1.2" - "@graphql-tools/utils" "^8.1.2" + "@graphql-tools/schema" "8.3.1" + "@graphql-tools/utils" "^8.5.5" p-limit "3.1.0" tslib "~2.3.0" -"@graphql-tools/merge@^8.0.2", "@graphql-tools/merge@^8.0.3": - version "8.0.3" - resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.0.3.tgz#56c844bc5d7d833456695c8e5eda4f1a0d5be873" - integrity sha512-lVMyW9cREs+nQYbUvMaaqSl+pRCezl2RafNMFi/04akjvOtjVefdi7n3pArpSqPhLHPJDyQRlI8CK8cmOZ9jTA== +"@graphql-tools/merge@^8.2.1": + version "8.2.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-8.2.1.tgz#bf83aa06a0cfc6a839e52a58057a84498d0d51ff" + integrity sha512-Q240kcUszhXiAYudjuJgNuLgy9CryDP3wp83NOZQezfA6h3ByYKU7xI6DiKrdjyVaGpYN3ppUmdj0uf5GaXzMA== dependencies: - "@graphql-tools/utils" "^8.1.2" + "@graphql-tools/utils" "^8.5.1" tslib "~2.3.0" -"@graphql-tools/schema@6.0.10": - version "6.0.10" - resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-6.0.10.tgz#69b36fad35ea5780f8539c92e776f9e83d929575" - integrity sha512-g8iy36dgf/Cpyz7bHSE2axkE8PdM5VYdS2tntmytLvPaN3Krb8IxBpZBJhmiICwyAAkruQE7OjDfYr8vP8jY4A== - dependencies: - "@graphql-tools/utils" "6.0.10" - tslib "~2.0.0" - -"@graphql-tools/schema@8.1.2", "@graphql-tools/schema@^8.1.2": - version "8.1.2" - resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-8.1.2.tgz#913879da1a7889a9488e9b7dc189e7c83eff74be" - integrity sha512-rX2pg42a0w7JLVYT+f/yeEKpnoZL5PpLq68TxC3iZ8slnNBNjfVfvzzOn8Q8Q6Xw3t17KP9QespmJEDfuQe4Rg== +"@graphql-tools/schema@8.3.1", "@graphql-tools/schema@^8.3.1": + version "8.3.1" + resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-8.3.1.tgz#1ee9da494d2da457643b3c93502b94c3c4b68c74" + integrity sha512-3R0AJFe715p4GwF067G5i0KCr/XIdvSfDLvTLEiTDQ8V/hwbOHEKHKWlEBHGRQwkG5lwFQlW1aOn7VnlPERnWQ== dependencies: - "@graphql-tools/merge" "^8.0.2" - "@graphql-tools/utils" "^8.1.1" + "@graphql-tools/merge" "^8.2.1" + "@graphql-tools/utils" "^8.5.1" tslib "~2.3.0" - value-or-promise "1.0.10" - -"@graphql-tools/stitch@^8.2.1": - version "8.2.1" - resolved "https://registry.yarnpkg.com/@graphql-tools/stitch/-/stitch-8.2.1.tgz#19f174e642b6e4ae16064215706acd59d71f6520" - integrity sha512-QZ4qu++9XwrSVL51DpmwRSpPkdS7ScbyTkHOtudAwQv/rti6RP+qlAaRwMLao1WZfjZDnNJj/JeXqnPHjHTj8w== - dependencies: - "@graphql-tools/batch-delegate" "8.0.12" - "@graphql-tools/delegate" "^8.1.1" - "@graphql-tools/merge" "^8.0.3" - "@graphql-tools/schema" "^8.1.2" - "@graphql-tools/utils" "^8.1.2" - "@graphql-tools/wrap" "^8.0.13" + value-or-promise "1.0.11" + +"@graphql-tools/stitch@^8.4.3": + version "8.4.3" + resolved "https://registry.yarnpkg.com/@graphql-tools/stitch/-/stitch-8.4.3.tgz#c5fd3cab23f72cc659e03b0127cbbb9aa7af8835" + integrity sha512-IOgKgMu/TeB0ZHOFHW147I/9LUo4NgRs7vqTqmTPVutiTR1YPYDdBWoQh+rhDBQN6gvxKq6EI/RcMGslbOMLvQ== + dependencies: + "@graphql-tools/batch-delegate" "8.2.3" + "@graphql-tools/delegate" "^8.4.3" + "@graphql-tools/merge" "^8.2.1" + "@graphql-tools/schema" "^8.3.1" + "@graphql-tools/utils" "^8.5.4" + "@graphql-tools/wrap" "^8.3.1" tslib "~2.3.0" -"@graphql-tools/utils@6.0.10": - version "6.0.10" - resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-6.0.10.tgz#ed15110a20acc5474a8dda5c0b99f970ba696c75" - integrity sha512-1s3vBnYUIDLBGEaV1VF3lv1Xq54lT8Oz7tNNypv7K7cv3auKX7idRtjP8RM6hKpGod46JNZgu3NNOshMUEyEyA== - dependencies: - aggregate-error "3.0.1" - camel-case "4.1.1" - -"@graphql-tools/utils@^8.1.1", "@graphql-tools/utils@^8.1.2": - version "8.1.2" - resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.1.2.tgz#a376259fafbca7532fda657e3abeec23b545e5d3" - integrity sha512-3G+NIBR5mHjPm78jAD0l07JRE0XH+lr9m7yL/wl69jAzK0Jr/H+/Ok4ljEolI70iglz+ZhIShVPAwyesF6rnFg== +"@graphql-tools/utils@8.5.5", "@graphql-tools/utils@^8.5.1", "@graphql-tools/utils@^8.5.3", "@graphql-tools/utils@^8.5.4", "@graphql-tools/utils@^8.5.5": + version "8.5.5" + resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-8.5.5.tgz#019ddb99719feb19602afdb537c06e463df674a9" + integrity sha512-y7zRXWIUI73X+9/rf/0KzrNFMlpRKFfzLiwdbIeWwgLs+NV9vfUOoVkX8luXX6LwQxhSypHATMiwZGM2ro/wJA== dependencies: tslib "~2.3.0" -"@graphql-tools/wrap@^8.0.13": - version "8.0.13" - resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-8.0.13.tgz#17a4096efbc64e15b27a74135d920c8bd3e5385a" - integrity sha512-GTkHbN+Zgs+D7bFniFx3/YqNIDv8ET17prM7FewmU8LNRc2P48y6d4/dkQLcwQmryy1TZF87es6yA9FMNfQtWg== +"@graphql-tools/wrap@^8.3.1", "@graphql-tools/wrap@^8.3.2": + version "8.3.2" + resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-8.3.2.tgz#d3bcecb7529d071e4ecc4dfc75b9566e3da79d4f" + integrity sha512-7DcOBFB+Dd84x9dxSm7qS4iJONMyfLnCJb8A19vGPffpu4SMJ3sFcgwibKFu5l6mMUiigKgXna2RRgWI+02bKQ== dependencies: - "@graphql-tools/delegate" "^8.1.0" - "@graphql-tools/schema" "^8.1.2" - "@graphql-tools/utils" "^8.1.1" + "@graphql-tools/delegate" "^8.4.2" + "@graphql-tools/schema" "^8.3.1" + "@graphql-tools/utils" "^8.5.3" tslib "~2.3.0" - value-or-promise "1.0.10" + value-or-promise "1.0.11" "@heroku/foreman@2.0.2": version "2.0.2" @@ -2086,14 +2061,6 @@ agent-base@5: resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c" integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g== -aggregate-error@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" - integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== - dependencies: - clean-stack "^2.0.0" - indent-string "^4.0.0" - ajv@^5.1.0: version "5.5.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.0.tgz#eb2840746e9dc48bd5e063a36e3fd400c5eab5a9" @@ -2958,14 +2925,6 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw== -camel-case@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.1.tgz#1fc41c854f00e2f7d0139dfeba1542d6896fe547" - integrity sha512-7fa2WcG4fYFkclIvEmxBbTvmibwF2/agfEBc6q3lOpVu0A13ltLsA+Hr/8Hp6kp5f+G7hKi6t8lys6XxP+1K6Q== - dependencies: - pascal-case "^3.1.1" - tslib "^1.10.0" - camelcase@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" @@ -3099,11 +3058,6 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -clean-stack@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" - integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== - cli-cursor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" @@ -5511,11 +5465,6 @@ indent-string@^3.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= -indent-string@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" - integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -7099,13 +7048,6 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1: dependencies: js-tokens "^3.0.0" -lower-case@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.1.tgz#39eeb36e396115cc05e29422eaea9e692c9408c7" - integrity sha512-LiWgfDLLb1dwbFQZsSglpRj+1ctGnayXz3Uv0/WO8n558JycT5fg6zkNcnW0G68Nn0aEldTFeEfmjCfmqry/rQ== - dependencies: - tslib "^1.10.0" - lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" @@ -7534,14 +7476,6 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -no-case@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.3.tgz#c21b434c1ffe48b39087e86cfb4d2582e9df18f8" - integrity sha512-ehY/mVQCf9BL0gKfsJBvFJen+1V//U+0HQMPrWct40ixE4jnv0bfvxDbWtAHL9EcaPEOJHVVYKoQn1TlZUB8Tw== - dependencies: - lower-case "^2.0.1" - tslib "^1.10.0" - node-cleanup@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/node-cleanup/-/node-cleanup-2.1.2.tgz#7ac19abd297e09a7f72a71545d951b517e4dde2c" @@ -8134,14 +8068,6 @@ parseurl@~1.3.2: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.2.tgz#fc289d4ed8993119460c156253262cdc8de65bf3" integrity sha1-/CidTtiZMRlGDBViUyYs3I3mW/M= -pascal-case@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.1.tgz#5ac1975133ed619281e88920973d2cd1f279de5f" - integrity sha512-XIeHKqIrsquVTQL2crjq3NfJUxmdLasn3TYOU0VBM+UX2a6ztAWBlJQBePLGY7VHW8+2dRadeIPK5+KImwTxQA== - dependencies: - no-case "^3.0.3" - tslib "^1.10.0" - pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" @@ -10045,11 +9971,6 @@ tsconfig-paths@^3.9.0: minimist "^1.2.0" strip-bom "^3.0.0" -tslib@^1.10.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" - integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== - tslib@^1.8.1: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" @@ -10060,16 +9981,6 @@ tslib@^1.9.0, tslib@^1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== -tslib@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3" - integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g== - -tslib@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" - integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== - tslib@~2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" @@ -10328,10 +10239,10 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -value-or-promise@1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.10.tgz#5bf041f1e9a8e7043911875547636768a836e446" - integrity sha512-1OwTzvcfXkAfabk60UVr5NdjtjJ0Fg0T5+B1bhxtrOEwSH2fe8y4DnLgoksfCyd8yZCOQQHB0qLMQnwgCjbXLQ== +value-or-promise@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.11.tgz#3e90299af31dd014fe843fe309cefa7c1d94b140" + integrity sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg== vary@^1, vary@~1.1.2: version "1.1.2" From 86fdc66980018f55f60cca375256e0564b1b461f Mon Sep 17 00:00:00 2001 From: Christopher Pappas Date: Fri, 17 Dec 2021 17:40:58 -0800 Subject: [PATCH 6/6] wip readd test files --- .../__snapshots__/schema.test.ts.snap | 108 ++++++++++++++++ .../stitching2/kaws/__tests__/schema.test.ts | 40 ++++++ .../kaws/__tests__/stitching.test.ts | 118 ++++++++++++++++++ .../stitching2/kaws/__tests__/testingUtils.ts | 45 +++++++ 4 files changed, 311 insertions(+) create mode 100644 src/lib/stitching2/kaws/__tests__/__snapshots__/schema.test.ts.snap create mode 100644 src/lib/stitching2/kaws/__tests__/schema.test.ts create mode 100644 src/lib/stitching2/kaws/__tests__/stitching.test.ts create mode 100644 src/lib/stitching2/kaws/__tests__/testingUtils.ts diff --git a/src/lib/stitching2/kaws/__tests__/__snapshots__/schema.test.ts.snap b/src/lib/stitching2/kaws/__tests__/__snapshots__/schema.test.ts.snap new file mode 100644 index 0000000000..00368c3156 --- /dev/null +++ b/src/lib/stitching2/kaws/__tests__/__snapshots__/schema.test.ts.snap @@ -0,0 +1,108 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`creates an SDL 1`] = ` +"type Collection { + id: ID! + slug: String! + title: String! + description: String + descriptionMarkdown: String + headerImage: String + thumbnail: String + keywords: String! + credit: String + category: String! + query: CollectionQuery! + createdAt: DateTime! + updatedAt: DateTime! + price_guidance: Float @deprecated(reason: \\"Prefer priceGuidance\\") + priceGuidance: Float + show_on_editorial: Boolean! @deprecated(reason: \\"Prefer showOnEditorial\\") + showOnEditorial: Boolean! + is_featured_artist_content: Boolean! @deprecated(reason: \\"Prefer isFeaturedArtistContent\\") + isFeaturedArtistContent: Boolean! + linkedCollections: [CollectionGroup!]! + featuredArtistExclusionIds: [String!] + relatedCollections(size: Int = 10): [Collection!]! + isDepartment: Boolean! +} + +type CollectionCategory { + name: String! + collections: [Collection!]! +} + +type CollectionGroup { + internalID: ID + groupType: GroupTypes! + name: String! + members: [Collection!]! +} + +type CollectionQuery { + id: ID + internalID: ID + acquireable: Boolean + aggregations: [String!] + artist_ids: [String!] @deprecated(reason: \\"Prefer artistIDs\\") + artistIDs: [String!] + artist_id: String @deprecated(reason: \\"Prefer artistID\\") + artistID: String + at_auction: Boolean @deprecated(reason: \\"Prefer atAuction\\") + atAuction: Boolean + color: String + dimension_range: String @deprecated(reason: \\"Prefer dimensionRange\\") + dimensionRange: String + extra_aggregation_gene_ids: [String!] @deprecated(reason: \\"prefer extraAggregationGeneIDs\\") + extraAggregationGeneIDs: [String!] + include_artworks_by_followed_artists: Boolean @deprecated(reason: \\"Prefer includeArtworksByFollowedArtists\\") + includeArtworksByFollowedArtists: Boolean + include_medium_filter_in_aggregation: Boolean @deprecated(reason: \\"Prefer includeMediumFilterInAggregation\\") + includeMediumFilterInAggregation: Boolean + inquireable_only: Boolean @deprecated(reason: \\"Prefer inquireableOnly\\") + inquireableOnly: Boolean + for_sale: Boolean @deprecated(reason: \\"Prefer forSale\\") + forSale: Boolean + gene_id: String @deprecated(reason: \\"Prefer geneID\\") + geneID: String + gene_ids: [String!] @deprecated(reason: \\"Prefer geneIDs\\") + geneIDs: [String!] + height: String + width: String + medium: String + period: String + periods: [String!] + major_periods: [String!] @deprecated(reason: \\"Prefer majorPeriods\\") + majorPeriods: [String!] + partner_id: ID @deprecated(reason: \\"Prefer partnerID\\") + partnerID: ID + partner_cities: [String!] @deprecated(reason: \\"Prefer partnerCities\\") + partnerCities: [String!] + price_range: String @deprecated(reason: \\"Prefer priceRange\\") + priceRange: String + page: Int + sale_id: ID @deprecated(reason: \\"Prefer saleID\\") + saleID: ID + size: Int + sort: String + tag_id: String @deprecated(reason: \\"Prefer tagID\\") + tagID: String + keyword: String +} + +scalar DateTime + +enum GroupTypes { + ArtistSeries + FeaturedCollections + OtherCollections +} + +type Query { + collections(slugs: [String!], category: String, randomizationSeed: String, size: Int, isFeaturedArtistContent: Boolean, showOnEditorial: Boolean, artistID: String): [Collection!]! + categories: [CollectionCategory!]! + collection(slug: String!): Collection + hubCollections: [Collection!]! +} +" +`; diff --git a/src/lib/stitching2/kaws/__tests__/schema.test.ts b/src/lib/stitching2/kaws/__tests__/schema.test.ts new file mode 100644 index 0000000000..1bc92cc6d3 --- /dev/null +++ b/src/lib/stitching2/kaws/__tests__/schema.test.ts @@ -0,0 +1,40 @@ +import { executableKawsSchema } from "../schema" +import { + getTypesFromSchema, + getRootFieldsFromSchema, +} from "lib/stitching/lib/getTypesFromSchema" +import { printSchema } from "graphql" +import { stitchSchemas } from "@graphql-tools/stitch" +import { incrementalMergeSchemas2 } from "lib/stitching2/mergeSchemas" + +it("Does not include kaws core types", async () => { + const stitchedSchema = incrementalMergeSchemas2({}) + const kawsSchema = await executableKawsSchema() + const schema = stitchSchemas({ + subschemas: [kawsSchema], + }) + debugger + const kawsTypes = await getTypesFromSchema(schema) + + expect(kawsTypes).not.toContain("Collection") + expect(kawsTypes).not.toContain("CollectionCategory") + expect(kawsTypes).not.toContain("CollectionQuery") + + expect(kawsTypes).toContain("MarketingCollection") +}) + +it("Does not include the root query fields", async () => { + const kawsSchema = await executableKawsSchema() + const rootFields = await getRootFieldsFromSchema(kawsSchema.schema) + + expect(rootFields).not.toContain("categories") + expect(rootFields).not.toContain("collection") + expect(rootFields).not.toContain("collections") +}) + +it("creates an SDL", async () => { + const kawsSchema = await executableKawsSchema() + expect( + printSchema(kawsSchema.schema, { commentDescriptions: true }) + ).toMatchSnapshot() +}) diff --git a/src/lib/stitching2/kaws/__tests__/stitching.test.ts b/src/lib/stitching2/kaws/__tests__/stitching.test.ts new file mode 100644 index 0000000000..53bde57d71 --- /dev/null +++ b/src/lib/stitching2/kaws/__tests__/stitching.test.ts @@ -0,0 +1,118 @@ +import { + getKawsMergedSchema, + getKawsStitchedSchema, +} from "lib/stitching/kaws/__tests__/testingUtils" +import { getFieldsForTypeFromSchema } from "lib/stitching/lib/getTypesFromSchema" + +describe("KAWS Stitching", () => { + it("extends the Viewer object", async () => { + const mergedSchema = await getKawsMergedSchema() + const viewerFields = await getFieldsForTypeFromSchema( + "Viewer", + mergedSchema + ) + expect(viewerFields).toContain("marketingCollections") + }) + + describe("HomePageMarketingCollectionsModule", () => { + it("extends the HomePageMarketingCollectionsModule object", async () => { + const mergedSchema = await getKawsMergedSchema() + const homePageMarketingCollectionsModuleFields = await getFieldsForTypeFromSchema( + "HomePageMarketingCollectionsModule", + mergedSchema + ) + expect(homePageMarketingCollectionsModuleFields).toContain("results") + }) + + it("returns an array even if the kaws request fails", async () => { + const { resolvers } = await getKawsStitchedSchema() + const resultsResolver = + resolvers.HomePageMarketingCollectionsModule.results.resolve + const delegateToSchemaMock = jest.fn() + delegateToSchemaMock.mockRejectedValue( + "simulating a kaws request failure" + ) + const mergeInfo = { delegateToSchema: delegateToSchemaMock } + const results = await resultsResolver({}, {}, {}, { mergeInfo }) + expect(results).toEqual([]) + }) + }) + + describe("MarketingCollection", () => { + it("extends the HomePageMarketingCollectionsModule object", async () => { + const mergedSchema = await getKawsMergedSchema() + const fields = await getFieldsForTypeFromSchema( + "MarketingCollection", + mergedSchema + ) + expect(fields).toContain("internalID") + }) + + it("returns the id", async () => { + const { resolvers } = await getKawsStitchedSchema() + const resolver = resolvers.MarketingCollection.internalID.resolve + const result = resolver({ id: "percy" }, {}, {}, {}) + expect(result).toEqual("percy") + }) + }) + + describe("marketingCollections", () => { + it("passes artist internalID to kaws' artistID arg when querying `... on Artist`", async () => { + const { resolvers } = await getKawsStitchedSchema() + const marketingCollectionsResolver = + resolvers.Artist.marketingCollections.resolve + const mergeInfo = { delegateToSchema: jest.fn() } + + await marketingCollectionsResolver( + { internalID: "artist-internal-id" }, + {}, + {}, + { mergeInfo } + ) + + expect(mergeInfo.delegateToSchema).toHaveBeenCalledWith( + expect.objectContaining({ + args: { artistID: "artist-internal-id" }, + fieldName: "marketingCollections", + }) + ) + }) + + it("passes through slugs when stitched under a fair", async () => { + const { resolvers } = await getKawsStitchedSchema() + const marketingCollectionsResolver = + resolvers.Fair.marketingCollections.resolve + const mergeInfo = { delegateToSchema: jest.fn() } + + await marketingCollectionsResolver( + { kawsCollectionSlugs: ["catty-collection"] }, + {}, + {}, + { mergeInfo } + ) + + expect(mergeInfo.delegateToSchema).toHaveBeenCalledWith( + expect.objectContaining({ + args: { slugs: ["catty-collection"] }, + fieldName: "marketingCollections", + }) + ) + }) + + it("returns an empty list when there are no kawsCollectionSlugs", async () => { + const { resolvers } = await getKawsStitchedSchema() + const marketingCollectionsResolver = + resolvers.Fair.marketingCollections.resolve + const mergeInfo = { delegateToSchema: jest.fn() } + + const result = await marketingCollectionsResolver( + { kawsCollectionSlugs: [] }, + {}, + {}, + { mergeInfo } + ) + + expect(result).toEqual([]) + }) + }) +}) diff --git a/src/lib/stitching2/kaws/__tests__/testingUtils.ts b/src/lib/stitching2/kaws/__tests__/testingUtils.ts new file mode 100644 index 0000000000..9bcdb9f6ee --- /dev/null +++ b/src/lib/stitching2/kaws/__tests__/testingUtils.ts @@ -0,0 +1,45 @@ +import { mergeSchemas } from "graphql-tools" +import { kawsStitchingEnvironmentV2 } from "../v2/stitching" +import { GraphQLSchema } from "graphql" +import { executableKawsSchema } from "../schema" +import localSchema from "schema/v2/schema" + +let cachedSchema: GraphQLSchema & { transforms: any } +let stitchedSchema: ReturnType +let mergedSchema: GraphQLSchema & { transforms: any } + +/** Gets a cached copy of the transformed kaws schema */ +export const getKawsTransformedSchema = async () => { + if (!cachedSchema) { + cachedSchema = await executableKawsSchema() + } + return cachedSchema +} + +/** Gets a cached copy of the stitched schema, independent of being merged into the local schema */ +export const getKawsStitchedSchema = async () => { + if (!stitchedSchema) { + const cachedSchema = await getKawsTransformedSchema() + stitchedSchema = kawsStitchingEnvironmentV2(localSchema, cachedSchema) + } + return stitchedSchema +} + +/** Gets a cached fully setup schema with kaws and the localSchema set up */ +export const getKawsMergedSchema = async () => { + if (!stitchedSchema) { + const cachedSchema = await getKawsTransformedSchema() + const { extensionSchema, resolvers } = await getKawsStitchedSchema() + + // The order should only matter in that extension schemas come after the + // objects that they are expected to build upon + mergedSchema = mergeSchemas({ + schemas: [localSchema, cachedSchema, extensionSchema], + resolvers: resolvers, + }) as GraphQLSchema & { transforms: any } + + const anyMergedSchema = mergedSchema as any + anyMergedSchema.__allowedLegacyNames = ["__id"] + } + return mergedSchema +}