feature: introduce types for query.graph method (#9031)

This commit is contained in:
Harminder Virk
2024-09-09 13:26:40 +05:30
committed by GitHub
parent a5e8a55d63
commit 32ebfa619f
4 changed files with 104 additions and 44 deletions

View File

@@ -54,6 +54,7 @@ declare module "@medusajs/types" {
[ContainerRegistrationKeys.CONFIG_MODULE]: ConfigModule
[ContainerRegistrationKeys.PG_CONNECTION]: Knex<any>
[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<const TEntry extends string>(
queryConfig: RemoteQueryObjectConfig<TEntry>,
const query: RemoteQueryFunction = async (
queryOptions:
| RemoteQueryObjectConfig<any>
| RemoteQueryObjectFromStringResult<any>
| RemoteJoinerQuery,
options?: RemoteJoinerOptions
): Promise<any>
async function query<
const TConfig extends RemoteQueryObjectFromStringResult<any>
>(queryConfig: TConfig, options?: RemoteJoinerOptions): Promise<any>
/**
* 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<any>
/**
* Query wrapper to provide specific API's and pre processing around remoteQuery.query
* @param query
* @param options
*/
async function query<const TEntry extends string>(
query:
| RemoteJoinerQuery
| RemoteQueryObjectConfig<TEntry>
| RemoteQueryObjectFromStringResult<any>,
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<string, unknown>,
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",

View File

@@ -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
}>()
})
})
})

View File

@@ -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<TEntry extends string> = {
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 = {
<const TEntry extends string>(
queryConfig: RemoteQueryObjectConfig<TEntry>,
options?: RemoteJoinerOptions
): Promise<Prettify<GraphResultSet<TEntry>>>
}
/*export type RemoteQueryReturnedData<TEntry extends string> =
TEntry extends keyof RemoteQueryEntryPoints
? Prettify<Omit<RemoteQueryEntryPoints[TEntry], ExcludedProps>>
@@ -69,6 +94,13 @@ export type RemoteQueryFunction = {
* @param options
*/
(query: RemoteJoinerQuery, options?: RemoteJoinerOptions): Promise<any>
/**
* 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

View File

@@ -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