Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(index): Provide a similar API to Query #9193

Merged
merged 16 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion integration-tests/modules/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
dist/
node_modules
*yarn-error.log

.medusa
112 changes: 70 additions & 42 deletions integration-tests/modules/__tests__/index/search.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,25 +58,35 @@ medusaIntegrationTestRunner({
// Timeout to allow indexing to finish
await setTimeout(2000)

const [results, count] = await indexEngine.queryAndCount(
{
select: {
const { data: results } = await indexEngine.query<"product">({
fields: [
"product.*",
"product.variants.*",
"product.variants.prices.*",
],
filters: {
product: {
variants: {
prices: {
amount: { $gt: 50 },
},
},
},
},
pagination: {
order: {
product: {
variants: {
prices: true,
prices: {
amount: "DESC",
},
},
},
},
where: {
"product.variants.prices.amount": { $gt: 50 },
},
},
{
orderBy: [{ "product.variants.prices.amount": "DESC" }],
}
)
})

expect(count).toBe(1)
expect(results.length).toBe(1)

const variants = results[0].variants

Expand Down Expand Up @@ -118,26 +128,36 @@ medusaIntegrationTestRunner({
// Timeout to allow indexing to finish
await setTimeout(2000)

const [results, count] = await indexEngine.queryAndCount(
{
select: {
const { data: results } = await indexEngine.query<"product">({
fields: [
"product.*",
"product.variants.*",
"product.variants.prices.*",
],
filters: {
product: {
variants: {
prices: {
amount: { $gt: 50 },
currency_code: { $eq: "AUD" },
},
},
},
},
pagination: {
order: {
product: {
variants: {
prices: true,
prices: {
amount: "DESC",
},
},
},
},
where: {
"product.variants.prices.amount": { $gt: 50 },
"product.variants.prices.currency_code": { $eq: "AUD" },
},
},
{
orderBy: [{ "product.variants.prices.amount": "DESC" }],
}
)
})

expect(count).toBe(1)
expect(results.length).toBe(1)

const variants = results[0].variants

Expand Down Expand Up @@ -179,32 +199,40 @@ medusaIntegrationTestRunner({

await setTimeout(5000)

const queryArgs = [
{
select: {
const queryArgs = {
fields: [
"product.*",
"product.variants.*",
"product.variants.prices.*",
],
filters: {
product: {
variants: {
prices: {
amount: { $gt: 50 },
currency_code: { $eq: "AUD" },
},
},
},
},
pagination: {
order: {
product: {
variants: {
prices: true,
prices: {
amount: "DESC",
},
},
},
},
where: {
"product.variants.prices.amount": { $gt: 50 },
"product.variants.prices.currency_code": { $eq: "AUD" },
},
},
{
orderBy: [{ "product.variants.prices.amount": "DESC" }],
},
]
}

await indexEngine.queryAndCount(...queryArgs)
await indexEngine.query<"product">(queryArgs)

const [results, count, perf] = await indexEngine.queryAndCount(
...queryArgs
const { data: results, metadata } = await indexEngine.query<"product">(
queryArgs
)

console.log(perf)
})
})
},
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/modules/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"skipLibCheck": true,
"downlevelIteration": true // to use ES5 specific tooling
},
"include": ["src"],
"include": ["src", "./medusa/**/*"],
"exclude": [
"./dist/**/*",
"__tests__",
Expand Down
1 change: 1 addition & 0 deletions packages/core/modules-sdk/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ export const ModulesDefinition: {
Modules.EVENT_BUS,
"logger",
ContainerRegistrationKeys.REMOTE_QUERY,
ContainerRegistrationKeys.QUERY,
],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
Expand Down
36 changes: 26 additions & 10 deletions packages/core/modules-sdk/src/utils/gql-schema-to-types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MedusaModule } from "../medusa-module"
import { FileSystem } from "@medusajs/utils"
import { FileSystem, toCamelCase } from "@medusajs/utils"
import { GraphQLSchema } from "graphql/type"
import { parse, printSchema } from "graphql"
import { codegen } from "@graphql-codegen/core"
Expand All @@ -21,13 +21,13 @@ function buildEntryPointsTypeMap(

return aliases.flatMap((alias) => {
const names = Array.isArray(alias.name) ? alias.name : [alias.name]
const entity = alias.args?.["entity"]
const entity = alias?.["entity"]
return names.map((aliasItem) => {
return {
entryPoint: aliasItem,
entityType: entity
? schema.includes(`export type ${entity} `)
? alias.args?.["entity"]
? alias?.["entity"]
: "any"
: "any",
}
Expand All @@ -39,19 +39,23 @@ function buildEntryPointsTypeMap(

async function generateTypes({
outputDir,
filename,
config,
}: {
outputDir: string
filename: string
config: Parameters<typeof codegen>[0]
}) {
const fileSystem = new FileSystem(outputDir)

let output = await codegen(config)
const entryPoints = buildEntryPointsTypeMap(output)

const interfaceName = toCamelCase(filename)

const remoteQueryEntryPoints = `
declare module '@medusajs/types' {
interface RemoteQueryEntryPoints {
interface ${interfaceName} {
${entryPoints
.map((entry) => ` ${entry.entryPoint}: ${entry.entityType}`)
.join("\n")}
Expand All @@ -60,19 +64,31 @@ ${entryPoints

output += remoteQueryEntryPoints

await fileSystem.create("remote-query-types.d.ts", output)
await fileSystem.create(
"index.d.ts",
"export * as RemoteQueryTypes from './remote-query-types'"
)
await fileSystem.create(filename + ".d.ts", output)

const doesBarrelExists = await fileSystem.exists("index.d.ts")
if (!doesBarrelExists) {
await fileSystem.create(
"index.d.ts",
`export * as ${interfaceName}Types from './${filename}'`
)
} else {
const content = await fileSystem.contents("index.d.ts")
if (!content.includes(`${interfaceName}Types`)) {
const newContent = `export * as ${interfaceName}Types from './${filename}'\n${content}`
await fileSystem.create("index.d.ts", newContent)
}
}
}

export async function gqlSchemaToTypes({
schema,
outputDir,
filename,
}: {
schema: GraphQLSchema
outputDir: string
filename: string
}) {
const config = {
documents: [],
Expand All @@ -98,5 +114,5 @@ export async function gqlSchemaToTypes({
},
}

await generateTypes({ outputDir, config })
await generateTypes({ outputDir, filename, config })
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
export type Maybe<T> = T | null
export type InputMaybe<T> = Maybe<T>
export type Exact<T extends { [key: string]: unknown }> = {
[K in keyof T]: T[K]
}
export type MakeOptional<T, K extends keyof T> = Omit<T, K> & {
[SubKey in K]?: Maybe<T[SubKey]>
}
export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & {
[SubKey in K]: Maybe<T[SubKey]>
}
export type MakeEmpty<
T extends { [key: string]: unknown },
K extends keyof T
> = { [_ in K]?: never }
export type Incremental<T> =
| T
| {
[P in keyof T]?: P extends " $fragmentName" | "__typename" ? T[P] : never
}
/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
ID: { input: string; output: string }
String: { input: string; output: string }
Boolean: { input: boolean; output: boolean }
Int: { input: number; output: number }
Float: { input: number; output: number }
}

export type Product = {
__typename?: "Product"
id?: Maybe<Scalars["String"]["output"]>
title?: Maybe<Scalars["String"]["output"]>
variants?: Maybe<Array<Maybe<ProductVariant>>>
}

export type ProductVariant = {
__typename?: "ProductVariant"
id?: Maybe<Scalars["String"]["output"]>
product_id?: Maybe<Scalars["String"]["output"]>
sku?: Maybe<Scalars["String"]["output"]>
prices?: Maybe<Array<Maybe<Price>>>
}

export type Price = {
__typename?: "Price"
amount?: Maybe<Scalars["Int"]["output"]>
}

export interface FixtureEntryPoints {
product_variant: ProductVariant
product_variants: ProductVariant
variant: ProductVariant
variants: ProductVariant
product: Product
products: Product
price: Price
prices: Price
}

declare module "../index-service-entry-points" {
interface IndexServiceEntryPoints extends FixtureEntryPoints {}
}
59 changes: 59 additions & 0 deletions packages/core/types/src/index/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { expectTypeOf } from "expect-type"
import "../__fixtures__/index-service-entry-points"
import { OperatorMap } from "../operator-map"
import { IndexQueryConfig, OrderBy } from "../query-config"

describe("IndexQueryConfig", () => {
it("should infer the config types properly", async () => {
type IndexConfig = IndexQueryConfig<"product">

expectTypeOf<IndexConfig["fields"]>().toEqualTypeOf<
(
| "id"
| "title"
| "variants.*"
| "variants.id"
| "variants.product_id"
| "variants.sku"
| "variants.prices.*"
| "variants.prices.amount"
)[]
>()

expectTypeOf<IndexConfig["filters"]>().toEqualTypeOf<
| {
id?: string | string[] | OperatorMap<string>
title?: string | string[] | OperatorMap<string>
variants?: {
id?: string | string[] | OperatorMap<string>
product_id?: string | string[] | OperatorMap<string>
sku?: string | string[] | OperatorMap<string>
prices?: {
amount?: number | number[] | OperatorMap<number>
}
}
}
| undefined
>()

expectTypeOf<IndexConfig["pagination"]>().toEqualTypeOf<
| {
skip?: number
take?: number
order?: {
id?: OrderBy
title?: OrderBy
variants?: {
id?: OrderBy
product_id?: OrderBy
sku?: OrderBy
prices?: {
amount?: OrderBy
}
}
}
}
| undefined
>()
})
})
Loading
Loading