diff --git a/packages/core/modules-sdk/src/medusa-app.ts b/packages/core/modules-sdk/src/medusa-app.ts index c587c564ea..b0dc7716cd 100644 --- a/packages/core/modules-sdk/src/medusa-app.ts +++ b/packages/core/modules-sdk/src/medusa-app.ts @@ -54,6 +54,7 @@ declare module "@medusajs/types" { [ContainerRegistrationKeys.CONFIG_MODULE]: ConfigModule [ContainerRegistrationKeys.PG_CONNECTION]: Knex [ContainerRegistrationKeys.REMOTE_QUERY]: RemoteQueryFunction + [ContainerRegistrationKeys.QUERY]: RemoteQueryFunction [ContainerRegistrationKeys.LOGGER]: Logger } } @@ -420,53 +421,24 @@ async function MedusaApp_({ customRemoteFetchData: remoteFetchData, }) - /** - * Query wrapper to provide specific API's and pre processing around remoteQuery.query - * @param queryConfig - * @param options - */ - async function query( - queryConfig: RemoteQueryObjectConfig, + const query: RemoteQueryFunction = async ( + queryOptions: + | RemoteQueryObjectConfig + | RemoteQueryObjectFromStringResult + | RemoteJoinerQuery, options?: RemoteJoinerOptions - ): Promise - - async function query< - const TConfig extends RemoteQueryObjectFromStringResult - >(queryConfig: TConfig, options?: RemoteJoinerOptions): Promise - - /** - * Query wrapper to provide specific API's and pre processing around remoteQuery.query - * @param query - * @param options - */ - async function query( - query: RemoteJoinerQuery, - options?: RemoteJoinerOptions - ): Promise - - /** - * Query wrapper to provide specific API's and pre processing around remoteQuery.query - * @param query - * @param options - */ - async function query( - query: - | RemoteJoinerQuery - | RemoteQueryObjectConfig - | RemoteQueryObjectFromStringResult, - options?: RemoteJoinerOptions - ) { - if (!isObject(query)) { + ) => { + if (!isObject(queryOptions)) { throw new MedusaError( MedusaError.Types.INVALID_DATA, "Invalid query, expected object and received something else." ) } - let normalizedQuery: any = query + let normalizedQuery: any = queryOptions - if ("__value" in query) { - normalizedQuery = query.__value + if ("__value" in queryOptions) { + normalizedQuery = queryOptions.__value } else if ( "entryPoint" in normalizedQuery || "service" in normalizedQuery @@ -478,20 +450,39 @@ async function MedusaApp_({ return await remoteQuery.query(normalizedQuery, undefined, options) } + /** * Query wrapper to provide specific GraphQL like API around remoteQuery.query * @param query * @param variables * @param options */ - query.gql = async function ( - query: string, - variables?: Record, - options?: RemoteJoinerOptions - ) { + query.gql = async function (query, variables?, options?) { return await remoteQuery.query(query, variables, options) } + /** + * Graph function uses the remoteQuery under the hood and + * returns a result set + */ + query.graph = async function (queryOptions, options) { + const normalizedQuery = remoteQueryObjectFromString(queryOptions).__value + const response = await remoteQuery.query( + normalizedQuery, + undefined, + options + ) + + if (Array.isArray(response)) { + return { data: response, metadata: undefined } + } + + return { + data: response.rows, + metadata: response.metadata, + } + } + const applyMigration = async ({ modulesNames, action = "run", diff --git a/packages/core/types/src/modules-sdk/__tests__/query.spec.ts b/packages/core/types/src/modules-sdk/__tests__/query.spec.ts new file mode 100644 index 0000000000..611ef58bfb --- /dev/null +++ b/packages/core/types/src/modules-sdk/__tests__/query.spec.ts @@ -0,0 +1,36 @@ +import { expectTypeOf } from "expect-type" +import { FixtureEntryPoints } from "../__fixtures__/remote-query" +import { + QueryGraphFunction, + RemoteQueryFunctionReturnPagination, +} from "../remote-query" + +describe("Query", () => { + describe("Infer via queryConfig", () => { + it("should infer return type of a known entry", async () => { + const graph = (() => {}) as unknown as QueryGraphFunction + const result = await graph({ + entryPoint: "product", + fields: ["handle", "id"], + }) + + expectTypeOf(result).toEqualTypeOf<{ + data: FixtureEntryPoints["product"][] + metadata?: RemoteQueryFunctionReturnPagination + }>() + }) + + it("should infer as any for an known entry", async () => { + const graph = (() => {}) as unknown as QueryGraphFunction + const result = await graph({ + entryPoint: "foo", + fields: ["handle", "id"], + }) + + expectTypeOf(result).toEqualTypeOf<{ + data: any[] + metadata?: RemoteQueryFunctionReturnPagination + }>() + }) + }) +}) diff --git a/packages/core/types/src/modules-sdk/remote-query.ts b/packages/core/types/src/modules-sdk/remote-query.ts index 10238d8199..a2047d5226 100644 --- a/packages/core/types/src/modules-sdk/remote-query.ts +++ b/packages/core/types/src/modules-sdk/remote-query.ts @@ -1,4 +1,6 @@ +import { Prettify } from "../common" import { RemoteJoinerOptions, RemoteJoinerQuery } from "../joiner" +import { RemoteQueryEntryPoints } from "./remote-query-entry-points" import { RemoteQueryObjectConfig, RemoteQueryObjectFromStringResult, @@ -12,6 +14,29 @@ export type RemoteQueryFunctionReturnPagination = { count: number } +/** + * The GraphResultSet presents a typed output for the + * result returned by the underlying remote query + */ +export type GraphResultSet = { + data: TEntry extends keyof RemoteQueryEntryPoints + ? RemoteQueryEntryPoints[TEntry][] + : any[] + metadata?: RemoteQueryFunctionReturnPagination +} + +/** + * QueryGraphFunction is a wrapper on top of remoteQuery + * that simplifies the input it accepts and returns + * a normalized/consistent output. + */ +export type QueryGraphFunction = { + ( + queryConfig: RemoteQueryObjectConfig, + options?: RemoteJoinerOptions + ): Promise>> +} + /*export type RemoteQueryReturnedData = TEntry extends keyof RemoteQueryEntryPoints ? Prettify> @@ -69,6 +94,13 @@ export type RemoteQueryFunction = { * @param options */ (query: RemoteJoinerQuery, options?: RemoteJoinerOptions): Promise + + /** + * Graph function uses the remoteQuery under the hood and + * returns a result set + */ + graph: QueryGraphFunction + /** * Query wrapper to provide specific GraphQL like API around remoteQuery.query * @param query diff --git a/packages/core/utils/src/common/container.ts b/packages/core/utils/src/common/container.ts index 78406c1b80..d0bb1e45c3 100644 --- a/packages/core/utils/src/common/container.ts +++ b/packages/core/utils/src/common/container.ts @@ -4,6 +4,7 @@ export const ContainerRegistrationKeys = { CONFIG_MODULE: "configModule", LOGGER: "logger", REMOTE_QUERY: "remoteQuery", + QUERY: "query", REMOTE_LINK: "remoteLink", FEATURE_FLAG_ROUTER: "featureFlagRouter", } as const