feat: Application types generation from project GQL schema's (#8995)
This commit is contained in:
1 parent
ac30a989f4
commit
2c5e72d141
92 files changed
+5088
-402
No files matched your search
@@ -66,7 +66,6 @@ medusaIntegrationTestRunner({
|
||||
},
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
{ throwIfKeyNotFound: true }
|
||||
)
|
||||
|
||||
@@ -127,7 +126,6 @@ medusaIntegrationTestRunner({
|
||||
},
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
{
|
||||
throwIfRelationNotFound: true,
|
||||
}
|
||||
@@ -171,7 +169,6 @@ medusaIntegrationTestRunner({
|
||||
},
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
{
|
||||
throwIfRelationNotFound: [Modules.PAYMENT],
|
||||
}
|
||||
|
||||
@@ -342,12 +342,19 @@ function buildLocalCommands(cli, isLocalProject) {
|
||||
command: `develop`,
|
||||
desc: `Start development server. Watches file and rebuilds when something changes`,
|
||||
builder: (_) =>
|
||||
_.option(`H`, {
|
||||
_.option("types", {
|
||||
type: "boolean",
|
||||
default: true,
|
||||
describe:
|
||||
"Generate automated types for modules inside the .medusa directory",
|
||||
})
|
||||
.option(`H`, {
|
||||
alias: `host`,
|
||||
type: `string`,
|
||||
default: defaultHost,
|
||||
describe: `Set host. Defaults to ${defaultHost}`,
|
||||
}).option(`p`, {
|
||||
})
|
||||
.option(`p`, {
|
||||
alias: `port`,
|
||||
type: `string`,
|
||||
default: process.env.PORT || defaultPort,
|
||||
@@ -371,12 +378,19 @@ function buildLocalCommands(cli, isLocalProject) {
|
||||
command: `start`,
|
||||
desc: `Start development server.`,
|
||||
builder: (_) =>
|
||||
_.option(`H`, {
|
||||
_.option("types", {
|
||||
type: "boolean",
|
||||
default: false,
|
||||
describe:
|
||||
"Generate automated types for modules inside the .medusa directory",
|
||||
})
|
||||
.option(`H`, {
|
||||
alias: `host`,
|
||||
type: `string`,
|
||||
default: defaultHost,
|
||||
describe: `Set host. Defaults to ${defaultHost}`,
|
||||
}).option(`p`, {
|
||||
})
|
||||
.option(`p`, {
|
||||
alias: `port`,
|
||||
type: `string`,
|
||||
default: process.env.PORT || defaultPort,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { IPricingModuleService } from "@medusajs/types"
|
||||
import { MedusaError, ModuleRegistrationName } from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||
|
||||
export interface GetVariantPriceSetsStepInput {
|
||||
variantIds: string[]
|
||||
@@ -24,21 +24,13 @@ export const getVariantPriceSetsStep = createStep(
|
||||
|
||||
const remoteQuery = container.resolve("remoteQuery")
|
||||
|
||||
const variantPriceSets = await remoteQuery(
|
||||
{
|
||||
variant: {
|
||||
fields: ["id"],
|
||||
price_set: {
|
||||
fields: ["id"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
variant: {
|
||||
const variantPriceSets = await remoteQuery({
|
||||
entryPoint: "variant",
|
||||
fields: ["id", "price_set.id"],
|
||||
variables: {
|
||||
id: data.variantIds,
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
const notFound: string[] = []
|
||||
const priceSetIds: string[] = []
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import { CartWorkflowDTO } from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
Modules,
|
||||
isObject,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { ContainerRegistrationKeys, isObject, Modules } from "@medusajs/utils"
|
||||
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||
|
||||
export interface RetrieveCartWithLinksStepInput {
|
||||
cart_or_cart_id: string | CartWorkflowDTO
|
||||
@@ -29,12 +24,17 @@ export const retrieveCartWithLinksStep = createStep(
|
||||
const remoteQuery = container.resolve(
|
||||
ContainerRegistrationKeys.REMOTE_QUERY
|
||||
)
|
||||
const query = remoteQueryObjectFromString({
|
||||
const query = {
|
||||
entryPoint: Modules.CART,
|
||||
fields,
|
||||
})
|
||||
variables: {
|
||||
cart: {
|
||||
id,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const [cart] = await remoteQuery(query, { cart: { id } })
|
||||
const [cart] = await remoteQuery(query)
|
||||
|
||||
return new StepResponse(cart)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
Modules,
|
||||
PromotionActions,
|
||||
} from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||
|
||||
export interface UpdateCartPromotionStepInput {
|
||||
id: string
|
||||
@@ -33,9 +33,10 @@ export const updateCartPromotionsStep = createStep(
|
||||
)
|
||||
|
||||
const existingCartPromotionLinks = await remoteQuery({
|
||||
cart_promotion: {
|
||||
__args: { cart_id: [id] },
|
||||
entryPoint: "cart_promotion",
|
||||
fields: ["cart_id", "promotion_id"],
|
||||
variables: {
|
||||
cart_id: [id],
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||
|
||||
/**
|
||||
* The remote query's details.
|
||||
@@ -164,7 +164,7 @@ export const useRemoteQueryStep = createStep(
|
||||
: undefined,
|
||||
}
|
||||
|
||||
const entities = await query(queryObject, undefined, config)
|
||||
const entities = await query(queryObjectConfig, config)
|
||||
const result = list ? entities : entities[0]
|
||||
|
||||
return new StepResponse(result)
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
LINKS,
|
||||
Modules,
|
||||
promiseAll,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
export type SetShippingOptionsPriceSetsStepInput = {
|
||||
@@ -28,16 +27,14 @@ async function getCurrentShippingOptionPriceSetsLinks(
|
||||
shippingOptionIds: string[],
|
||||
{ remoteQuery }: { remoteQuery: RemoteQueryFunction }
|
||||
): Promise<LinkItems> {
|
||||
const query = remoteQueryObjectFromString({
|
||||
const shippingOptionPriceSetLinks = (await remoteQuery({
|
||||
service: LINKS.ShippingOptionPriceSet,
|
||||
variables: {
|
||||
filters: { shipping_option_id: shippingOptionIds },
|
||||
take: null,
|
||||
},
|
||||
fields: ["shipping_option_id", "price_set_id"],
|
||||
})
|
||||
|
||||
const shippingOptionPriceSetLinks = (await remoteQuery(query)) as {
|
||||
} as any)) as {
|
||||
shipping_option_id: string
|
||||
price_set_id: string
|
||||
}[]
|
||||
|
||||
@@ -10,12 +10,11 @@ import {
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
isDefined,
|
||||
LINKS,
|
||||
ModuleRegistrationName,
|
||||
isDefined,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||
|
||||
interface PriceRegionId {
|
||||
region_id: string
|
||||
@@ -33,16 +32,14 @@ async function getCurrentShippingOptionPrices(
|
||||
): Promise<
|
||||
{ shipping_option_id: string; price_set_id: string; prices: PriceDTO[] }[]
|
||||
> {
|
||||
const query = remoteQueryObjectFromString({
|
||||
const shippingOptionPrices = (await remoteQuery({
|
||||
service: LINKS.ShippingOptionPriceSet,
|
||||
variables: {
|
||||
filters: { shipping_option_id: shippingOptionIds },
|
||||
take: null,
|
||||
},
|
||||
fields: ["shipping_option_id", "price_set_id", "price_set.prices.*"],
|
||||
})
|
||||
|
||||
const shippingOptionPrices = (await remoteQuery(query)) as {
|
||||
} as any)) as {
|
||||
shipping_option_id: string
|
||||
price_set_id: string
|
||||
price_set: PriceSetDTO
|
||||
|
||||
@@ -3,9 +3,8 @@ import {
|
||||
ContainerRegistrationKeys,
|
||||
MedusaError,
|
||||
ModuleRegistrationName,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||
|
||||
export type FulfillmentProviderValidationWorkflowInput = {
|
||||
id?: string
|
||||
@@ -21,7 +20,10 @@ export const validateFulfillmentProvidersStepId =
|
||||
*/
|
||||
export const validateFulfillmentProvidersStep = createStep(
|
||||
validateFulfillmentProvidersStepId,
|
||||
async (input: FulfillmentProviderValidationWorkflowInput[], { container }) => {
|
||||
async (
|
||||
input: FulfillmentProviderValidationWorkflowInput[],
|
||||
{ container }
|
||||
) => {
|
||||
const dataToValidate: {
|
||||
service_zone_id: string
|
||||
provider_id: string
|
||||
@@ -83,7 +85,7 @@ export const validateFulfillmentProvidersStep = createStep(
|
||||
)
|
||||
}
|
||||
|
||||
const serviceZoneQuery = remoteQueryObjectFromString({
|
||||
const serviceZones = await remoteQuery({
|
||||
entryPoint: "service_zone",
|
||||
fields: ["id", "fulfillment_set.locations.fulfillment_providers.id"],
|
||||
variables: {
|
||||
@@ -91,8 +93,6 @@ export const validateFulfillmentProvidersStep = createStep(
|
||||
},
|
||||
})
|
||||
|
||||
const serviceZones = await remoteQuery(serviceZoneQuery)
|
||||
|
||||
const serviceZonesMap = new Map<
|
||||
string,
|
||||
ServiceZoneDTO & {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {
|
||||
arrayDifference,
|
||||
ContainerRegistrationKeys,
|
||||
MedusaError,
|
||||
arrayDifference,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { createStep } from "@medusajs/workflows-sdk"
|
||||
|
||||
@@ -17,13 +16,11 @@ export const validateInventoryItems = createStep(
|
||||
ContainerRegistrationKeys.REMOTE_QUERY
|
||||
)
|
||||
|
||||
const query = remoteQueryObjectFromString({
|
||||
const items = await remoteQuery({
|
||||
entryPoint: "inventory_item",
|
||||
variables: { id },
|
||||
fields: ["id"],
|
||||
})
|
||||
|
||||
const items = await remoteQuery(query)
|
||||
const diff = arrayDifference(
|
||||
id,
|
||||
items.map(({ id }) => id)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import {
|
||||
arrayDifference,
|
||||
ContainerRegistrationKeys,
|
||||
MedusaError,
|
||||
arrayDifference,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
|
||||
import { InventoryTypes } from "@medusajs/types"
|
||||
@@ -19,7 +18,7 @@ export const validateInventoryLocationsStep = createStep(
|
||||
ContainerRegistrationKeys.REMOTE_QUERY
|
||||
)
|
||||
|
||||
const locationQuery = remoteQueryObjectFromString({
|
||||
const stockLocations = await remoteQuery({
|
||||
entryPoint: "stock_location",
|
||||
variables: {
|
||||
id: data.map((d) => d.location_id),
|
||||
@@ -27,8 +26,6 @@ export const validateInventoryLocationsStep = createStep(
|
||||
fields: ["id"],
|
||||
})
|
||||
|
||||
const stockLocations = await remoteQuery(locationQuery)
|
||||
|
||||
const diff = arrayDifference(
|
||||
data.map((d) => d.location_id),
|
||||
stockLocations.map((l) => l.id)
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
MedusaError,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { ContainerRegistrationKeys, MedusaError } from "@medusajs/utils"
|
||||
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||
|
||||
export const validateVariantPriceLinksStepId = "validate-variant-price-links"
|
||||
/**
|
||||
@@ -28,13 +24,11 @@ export const validateVariantPriceLinksStep = createStep(
|
||||
.filter(Boolean)
|
||||
.flat(1)
|
||||
|
||||
const variantPricingLinkQuery = remoteQueryObjectFromString({
|
||||
const links = await remoteQuery({
|
||||
entryPoint: "product_variant_price_set",
|
||||
fields: ["variant_id", "price_set_id"],
|
||||
variables: { variant_id: variantIds, take: null },
|
||||
})
|
||||
|
||||
const links = await remoteQuery(variantPricingLinkQuery)
|
||||
const variantPriceSetMap: Record<string, string> = {}
|
||||
|
||||
for (const link of links) {
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { FilterableProductProps, RemoteQueryFunction } from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { ContainerRegistrationKeys } from "@medusajs/utils"
|
||||
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||
|
||||
export type GetAllProductsStepInput = {
|
||||
@@ -27,7 +24,7 @@ export const getAllProductsStep = createStep(
|
||||
|
||||
// We intentionally fetch the products serially here to avoid putting too much load on the DB
|
||||
while (true) {
|
||||
const remoteQueryObject = remoteQueryObjectFromString({
|
||||
const { rows: products } = await remoteQuery({
|
||||
entryPoint: "product",
|
||||
variables: {
|
||||
filters: data.filter,
|
||||
@@ -36,8 +33,6 @@ export const getAllProductsStep = createStep(
|
||||
},
|
||||
fields: data.select,
|
||||
})
|
||||
|
||||
const { rows: products } = await remoteQuery(remoteQueryObject)
|
||||
allProducts.push(...products)
|
||||
|
||||
if (products.length < pageSize) {
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import { RemoteLink } from "@medusajs/modules-sdk"
|
||||
import { IPaymentModuleService, RemoteQueryFunction } from "@medusajs/types"
|
||||
import {
|
||||
arrayDifference,
|
||||
ContainerRegistrationKeys,
|
||||
LINKS,
|
||||
MedusaError,
|
||||
ModuleRegistrationName,
|
||||
Modules,
|
||||
arrayDifference,
|
||||
promiseAll,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
|
||||
import { createStep, StepResponse } from "@medusajs/workflows-sdk"
|
||||
|
||||
export interface SetRegionsPaymentProvidersStepInput {
|
||||
input: {
|
||||
@@ -64,16 +63,14 @@ async function getCurrentRegionPaymentProvidersLinks(
|
||||
[Modules.PAYMENT]: { payment_provider_id: string }
|
||||
}[]
|
||||
> {
|
||||
const query = remoteQueryObjectFromString({
|
||||
const regionProviderLinks = (await remoteQuery({
|
||||
service: LINKS.RegionPaymentProvider,
|
||||
variables: {
|
||||
filters: { region_id: regionIds },
|
||||
take: null,
|
||||
},
|
||||
fields: ["region_id", "payment_provider_id"],
|
||||
})
|
||||
|
||||
const regionProviderLinks = (await remoteQuery(query)) as {
|
||||
} as any)) as {
|
||||
region_id: string
|
||||
payment_provider_id: string
|
||||
}[]
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
"typescript": "^5.1.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@graphql-codegen/cli": "^5.0.2",
|
||||
"@graphql-codegen/typescript": "^4.0.9",
|
||||
"@graphql-tools/merge": "^9.0.0",
|
||||
"@graphql-tools/schema": "^10.0.0",
|
||||
"@medusajs/orchestration": "^0.5.7",
|
||||
|
||||
@@ -5,3 +5,4 @@ export * from "./medusa-module"
|
||||
export * from "./remote-link"
|
||||
export * from "./remote-query"
|
||||
export * from "./types"
|
||||
export { gqlSchemaToTypes } from "./utils"
|
||||
@@ -17,20 +17,24 @@ import {
|
||||
RemoteJoinerOptions,
|
||||
RemoteJoinerQuery,
|
||||
RemoteQueryFunction,
|
||||
RemoteQueryObjectConfig,
|
||||
RemoteQueryObjectFromStringResult,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
createMedusaContainer,
|
||||
isObject,
|
||||
isString,
|
||||
MedusaError,
|
||||
ModuleRegistrationName,
|
||||
Modules,
|
||||
ModulesSdkUtils,
|
||||
createMedusaContainer,
|
||||
isObject,
|
||||
isString,
|
||||
promiseAll,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import type { Knex } from "@mikro-orm/knex"
|
||||
import { asValue } from "awilix"
|
||||
import { GraphQLSchema } from "graphql/type"
|
||||
import { MODULE_PACKAGE_NAMES } from "./definitions"
|
||||
import {
|
||||
MedusaModule,
|
||||
@@ -227,6 +231,7 @@ export type MedusaAppOutput = {
|
||||
link: RemoteLink | undefined
|
||||
query: RemoteQueryFunction
|
||||
entitiesMap?: Record<string, any>
|
||||
gqlSchema?: GraphQLSchema
|
||||
notFound?: Record<string, Record<string, string>>
|
||||
runMigrations: RunMigrationFn
|
||||
revertMigrations: RevertMigrationFn
|
||||
@@ -352,15 +357,17 @@ async function MedusaApp_({
|
||||
)
|
||||
|
||||
if (loaderOnly) {
|
||||
async function query(...args: Parameters<RemoteQueryFunction>) {
|
||||
throw new Error("Querying not allowed in loaderOnly mode")
|
||||
}
|
||||
|
||||
return {
|
||||
onApplicationShutdown,
|
||||
onApplicationPrepareShutdown,
|
||||
onApplicationStart,
|
||||
modules: allModules,
|
||||
link: undefined,
|
||||
query: async () => {
|
||||
throw new Error("Querying not allowed in loaderOnly mode")
|
||||
},
|
||||
query: query as RemoteQueryFunction,
|
||||
runMigrations: async () => {
|
||||
throw new Error("Migrations not allowed in loaderOnly mode")
|
||||
},
|
||||
@@ -413,11 +420,75 @@ async function MedusaApp_({
|
||||
customRemoteFetchData: remoteFetchData,
|
||||
})
|
||||
|
||||
const query = async (
|
||||
query: string | RemoteJoinerQuery | object,
|
||||
/**
|
||||
* 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>,
|
||||
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)) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
"Invalid query, expected object and received something else."
|
||||
)
|
||||
}
|
||||
|
||||
let normalizedQuery: any = query
|
||||
|
||||
if ("__value" in query) {
|
||||
normalizedQuery = query.__value
|
||||
} else if (
|
||||
"entryPoint" in normalizedQuery ||
|
||||
"service" in normalizedQuery
|
||||
) {
|
||||
normalizedQuery = remoteQueryObjectFromString(
|
||||
normalizedQuery as Parameters<typeof remoteQueryObjectFromString>[0]
|
||||
).__value
|
||||
}
|
||||
|
||||
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
|
||||
) => {
|
||||
) {
|
||||
return await remoteQuery.query(query, variables, options)
|
||||
}
|
||||
|
||||
@@ -524,6 +595,7 @@ async function MedusaApp_({
|
||||
link: remoteLink,
|
||||
query,
|
||||
entitiesMap: schema.getTypeMap(),
|
||||
gqlSchema: schema,
|
||||
notFound,
|
||||
runMigrations,
|
||||
revertMigrations,
|
||||
|
||||
@@ -145,7 +145,7 @@ export class RemoteQuery {
|
||||
return {
|
||||
skip: options.skip,
|
||||
take: options.take,
|
||||
cursor: options.cursor,
|
||||
// cursor: options.cursor, not yet supported
|
||||
// TODO: next cursor
|
||||
count,
|
||||
}
|
||||
|
||||
@@ -7,3 +7,5 @@ export enum MODULE_RESOURCE_TYPE {
|
||||
SHARED = "shared",
|
||||
ISOLATED = "isolated",
|
||||
}
|
||||
|
||||
export { GraphQLSchema } from "graphql"
|
||||
@@ -0,0 +1,99 @@
|
||||
import { MedusaModule } from "../medusa-module"
|
||||
import { FileSystem } from "@medusajs/utils"
|
||||
import { GraphQLSchema } from "graphql/type"
|
||||
import { parse, printSchema } from "graphql"
|
||||
import { codegen } from "@graphql-codegen/core"
|
||||
import * as typescriptPlugin from "@graphql-codegen/typescript"
|
||||
|
||||
function buildEntryPointsTypeMap(
|
||||
schema: string
|
||||
): { entryPoint: string; entityType: any }[] {
|
||||
// build map entry point to there type to be merged and used by the remote query
|
||||
|
||||
const joinerConfigs = MedusaModule.getAllJoinerConfigs()
|
||||
return joinerConfigs
|
||||
.flatMap((config) => {
|
||||
const aliases = Array.isArray(config.alias)
|
||||
? config.alias
|
||||
: config.alias
|
||||
? [config.alias]
|
||||
: []
|
||||
|
||||
return aliases.flatMap((alias) => {
|
||||
const names = Array.isArray(alias.name) ? alias.name : [alias.name]
|
||||
const entity = alias.args?.["entity"]
|
||||
return names.map((aliasItem) => {
|
||||
return {
|
||||
entryPoint: aliasItem,
|
||||
entityType: entity
|
||||
? schema.includes(`export type ${entity} `)
|
||||
? alias.args?.["entity"]
|
||||
: "any"
|
||||
: "any",
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
.filter(Boolean)
|
||||
}
|
||||
|
||||
async function generateTypes({
|
||||
outputDir,
|
||||
config,
|
||||
}: {
|
||||
outputDir: string
|
||||
config: Parameters<typeof codegen>[0]
|
||||
}) {
|
||||
const fileSystem = new FileSystem(outputDir)
|
||||
|
||||
let output = await codegen(config)
|
||||
const entryPoints = buildEntryPointsTypeMap(output)
|
||||
|
||||
const remoteQueryEntryPoints = `
|
||||
declare module '@medusajs/types' {
|
||||
interface RemoteQueryEntryPoints {
|
||||
${entryPoints
|
||||
.map((entry) => ` ${entry.entryPoint}: ${entry.entityType}`)
|
||||
.join("\n")}
|
||||
}
|
||||
}`
|
||||
|
||||
output += remoteQueryEntryPoints
|
||||
|
||||
await fileSystem.create("remote-query-types.d.ts", output)
|
||||
await fileSystem.create(
|
||||
"index.d.ts",
|
||||
"export * as RemoteQueryTypes from './remote-query-types'"
|
||||
)
|
||||
}
|
||||
|
||||
export async function gqlSchemaToTypes({
|
||||
schema,
|
||||
outputDir,
|
||||
}: {
|
||||
schema: GraphQLSchema
|
||||
outputDir: string
|
||||
}) {
|
||||
const config = {
|
||||
documents: [],
|
||||
config: {
|
||||
scalars: {
|
||||
DateTime: { output: "Date | string" },
|
||||
JSON: { output: "Record<any, unknown>" },
|
||||
},
|
||||
},
|
||||
filename: "",
|
||||
schema: parse(printSchema(schema as any)),
|
||||
plugins: [
|
||||
// Each plugin should be an object
|
||||
{
|
||||
typescript: {}, // Here you can pass configuration to the plugin
|
||||
},
|
||||
],
|
||||
pluginMap: {
|
||||
typescript: typescriptPlugin,
|
||||
},
|
||||
}
|
||||
|
||||
await generateTypes({ outputDir, config })
|
||||
}
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from "./clean-graphql-schema"
|
||||
export * from "./graphql-schema-to-fields"
|
||||
export * from "./gql-schema-to-types"
|
||||
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
moduleNameMapper: {},
|
||||
transform: {
|
||||
"^.+\\.[jt]s$": [
|
||||
"@swc/jest",
|
||||
{
|
||||
jsc: {
|
||||
parser: { syntax: "typescript", decorators: true },
|
||||
transform: { decoratorMetadata: true },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
testEnvironment: `node`,
|
||||
moduleFileExtensions: [`js`, `ts`],
|
||||
modulePathIgnorePatterns: ["dist/"],
|
||||
}
|
||||
@@ -24,6 +24,7 @@
|
||||
"awilix": "^8.0.1",
|
||||
"bignumber.js": "^9.1.2",
|
||||
"cross-env": "^5.2.1",
|
||||
"expect-type": "^0.20.0",
|
||||
"ioredis": "^5.4.1",
|
||||
"rimraf": "^5.0.1",
|
||||
"typescript": "^5.1.6",
|
||||
@@ -31,7 +32,7 @@
|
||||
"winston": "^3.8.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "rimraf dist && tsc --build",
|
||||
"build": "rimraf dist && tsc -p tsconfig.spec.json --noEmit && tsc -p tsconfig.build.json",
|
||||
"watch": "tsc --build --watch",
|
||||
"test": "exit 0"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
// TODO: The intent is to manage fields picking from a object, not to act upon at the moment and just keeping it here for reference.
|
||||
|
||||
import { Prettify } from "./common"
|
||||
|
||||
type Split<S extends string, D extends string> = string extends S
|
||||
? string[]
|
||||
: S extends ""
|
||||
? []
|
||||
: S extends `${infer T}${D}${infer U}`
|
||||
? [T, ...Split<U, D>]
|
||||
: [S]
|
||||
|
||||
type NestedPickHelper<T, Path extends string[]> = Path extends [
|
||||
infer First,
|
||||
...infer Rest
|
||||
]
|
||||
? First extends keyof T
|
||||
? Rest extends string[]
|
||||
? Rest["length"] extends 0
|
||||
? T[First]
|
||||
: T[First] extends Array<infer Item>
|
||||
? {
|
||||
[K in keyof Item as Rest[0] extends "*"
|
||||
? K
|
||||
: K extends Rest[number]
|
||||
? K
|
||||
: never]: Item[K] extends object
|
||||
? NestedPickHelper<Item[K], Rest>
|
||||
: Item[K] extends Array<infer Item>
|
||||
? NestedPickHelper<Item, Rest>
|
||||
: Rest[0] extends "*"
|
||||
? Item[K]
|
||||
: K extends Rest[number]
|
||||
? Item[K]
|
||||
: never
|
||||
}[]
|
||||
: T[First] extends object
|
||||
? {
|
||||
[K in keyof T[First] as Rest[0] extends "*"
|
||||
? K
|
||||
: K extends Rest[number]
|
||||
? K
|
||||
: never]: T[First][K] extends object
|
||||
? NestedPickHelper<T[First], Rest>
|
||||
: T[First][K] extends Array<infer Item>
|
||||
? NestedPickHelper<Item, Rest>
|
||||
: Rest[0] extends "*"
|
||||
? T[First][K]
|
||||
: K extends Rest[number]
|
||||
? T[First][K]
|
||||
: never
|
||||
}
|
||||
: First extends "*"
|
||||
? {
|
||||
[K in keyof T]: T[K]
|
||||
}
|
||||
: {
|
||||
[K in keyof T[First] as K extends Rest[number]
|
||||
? K
|
||||
: never]: NestedPickHelper<T[First], Rest>
|
||||
}
|
||||
: never
|
||||
: First extends `${infer ArrayKey}[${infer Index}]`
|
||||
? ArrayKey extends keyof T
|
||||
? T[ArrayKey] extends (infer U)[]
|
||||
? NestedPickHelper<U, Rest & string[]>
|
||||
: never
|
||||
: never
|
||||
: First extends "*"
|
||||
? T
|
||||
: never
|
||||
: T
|
||||
|
||||
type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends (
|
||||
x: infer I
|
||||
) => void
|
||||
? I
|
||||
: never
|
||||
|
||||
export type NestedPickFirstIteration<T, Props extends string[]> = {
|
||||
[P in Props[number] as Split<P, ".">[0] & string]: NestedPickHelper<
|
||||
T,
|
||||
Split<P, ".">
|
||||
>
|
||||
}
|
||||
|
||||
type NestedPick<T, Props extends string[]> = {
|
||||
[K in keyof NestedPickFirstIteration<T, Props>]: Prettify<
|
||||
NestedPickFirstIteration<T, Props>[K] extends Array<infer V>
|
||||
? UnionToIntersection<V>[]
|
||||
: UnionToIntersection<NestedPickFirstIteration<T, Props>[K]>
|
||||
>
|
||||
}
|
||||
|
||||
type Obj = {
|
||||
id: string
|
||||
title: string
|
||||
variant: {
|
||||
id: string
|
||||
description: string
|
||||
}
|
||||
options: { id: string; value: string }[]
|
||||
extra: {
|
||||
detail: {
|
||||
name: string
|
||||
info: {
|
||||
data: string
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Test = NestedPick<
|
||||
Obj,
|
||||
[
|
||||
"id",
|
||||
"variant.description",
|
||||
"variant.id",
|
||||
"options.id",
|
||||
"options.value",
|
||||
"extra.detail.info.data"
|
||||
]
|
||||
>
|
||||
|
||||
const test: Test = {
|
||||
id: "test",
|
||||
variant: {
|
||||
description: "test",
|
||||
id: "test",
|
||||
},
|
||||
options: [
|
||||
{
|
||||
id: "test",
|
||||
value: "test",
|
||||
},
|
||||
],
|
||||
extra: {
|
||||
detail: {
|
||||
info: {
|
||||
data: "test",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,458 @@
|
||||
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 }
|
||||
DateTime: {
|
||||
input: { output: "Date | string" }
|
||||
output: { output: "Date | string" }
|
||||
}
|
||||
JSON: {
|
||||
input: { output: "Record<any, unknown>" }
|
||||
output: { output: "Record<any, unknown>" }
|
||||
}
|
||||
}
|
||||
|
||||
export type SimpleProduct = {
|
||||
id: Scalars["ID"]["output"]
|
||||
handle: string
|
||||
title?: Scalars["String"]["output"]
|
||||
variants?: Maybe<Array<Maybe<Pick<ProductVariant, "id">>>>
|
||||
sales_channels_link?: Array<
|
||||
Pick<LinkProductSalesChannel, "product_id" | "sales_channel_id">
|
||||
>
|
||||
sales_channels?: Array<Pick<SalesChannel, "id" | "name">>
|
||||
}
|
||||
|
||||
export type Product = {
|
||||
__typename?: "Product"
|
||||
id: Scalars["ID"]["output"]
|
||||
handle: Scalars["String"]["output"]
|
||||
title: Scalars["String"]["output"]
|
||||
description?: Scalars["String"]["output"]
|
||||
variants?: Array<ProductVariant>
|
||||
sales_channels_link?: Array<LinkProductSalesChannel>
|
||||
sales_channels?: Array<SalesChannel>
|
||||
}
|
||||
|
||||
export type ProductVariant = {
|
||||
__typename?: "ProductVariant"
|
||||
id: Scalars["ID"]["output"]
|
||||
handle: Scalars["String"]["output"]
|
||||
title: Scalars["String"]["output"]
|
||||
product?: Maybe<Product>
|
||||
}
|
||||
|
||||
export type ProductCategory = {
|
||||
__typename?: "ProductCategory"
|
||||
id: Scalars["ID"]["output"]
|
||||
handle: Scalars["String"]["output"]
|
||||
title?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type SalesChannel = {
|
||||
__typename?: "SalesChannel"
|
||||
id: Scalars["ID"]["output"]
|
||||
name?: Maybe<Scalars["String"]["output"]>
|
||||
description?: Maybe<Scalars["String"]["output"]>
|
||||
created_at?: Maybe<Scalars["DateTime"]["output"]>
|
||||
updated_at?: Maybe<Scalars["DateTime"]["output"]>
|
||||
products_link?: Maybe<Array<Maybe<LinkProductSalesChannel>>>
|
||||
api_keys_link?: Maybe<Array<Maybe<LinkPublishableApiKeySalesChannel>>>
|
||||
locations_link?: Maybe<Array<Maybe<LinkSalesChannelStockLocation>>>
|
||||
}
|
||||
|
||||
export type LinkCartPaymentCollection = {
|
||||
__typename?: "LinkCartPaymentCollection"
|
||||
cart_id: Scalars["String"]["output"]
|
||||
payment_collection_id: Scalars["String"]["output"]
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkCartPromotion = {
|
||||
__typename?: "LinkCartPromotion"
|
||||
cart_id: Scalars["String"]["output"]
|
||||
promotion_id: Scalars["String"]["output"]
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkLocationFulfillmentProvider = {
|
||||
__typename?: "LinkLocationFulfillmentProvider"
|
||||
stock_location_id: Scalars["String"]["output"]
|
||||
fulfillment_provider_id: Scalars["String"]["output"]
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkLocationFulfillmentSet = {
|
||||
__typename?: "LinkLocationFulfillmentSet"
|
||||
stock_location_id: Scalars["String"]["output"]
|
||||
fulfillment_set_id: Scalars["String"]["output"]
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkOrderCart = {
|
||||
__typename?: "LinkOrderCart"
|
||||
order_id: Scalars["String"]["output"]
|
||||
cart_id: Scalars["String"]["output"]
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkOrderFulfillment = {
|
||||
__typename?: "LinkOrderFulfillment"
|
||||
order_id: Scalars["String"]["output"]
|
||||
fulfillment_id: Scalars["String"]["output"]
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkOrderPaymentCollection = {
|
||||
__typename?: "LinkOrderPaymentCollection"
|
||||
order_id: Scalars["String"]["output"]
|
||||
payment_collection_id: Scalars["String"]["output"]
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkOrderPromotion = {
|
||||
__typename?: "LinkOrderPromotion"
|
||||
order_id: Scalars["String"]["output"]
|
||||
promotion_id: Scalars["String"]["output"]
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkReturnFulfillment = {
|
||||
__typename?: "LinkReturnFulfillment"
|
||||
return_id: Scalars["String"]["output"]
|
||||
fulfillment_id: Scalars["String"]["output"]
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkProductSalesChannel = {
|
||||
__typename?: "LinkProductSalesChannel"
|
||||
product_id: Scalars["String"]["output"]
|
||||
sales_channel_id: Scalars["String"]["output"]
|
||||
product?: Maybe<Product>
|
||||
sales_channel?: Maybe<SalesChannel>
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkProductVariantInventoryItem = {
|
||||
__typename?: "LinkProductVariantInventoryItem"
|
||||
variant_id: Scalars["String"]["output"]
|
||||
inventory_item_id: Scalars["String"]["output"]
|
||||
required_quantity: Scalars["Int"]["output"]
|
||||
variant?: Maybe<Product>
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkProductVariantPriceSet = {
|
||||
__typename?: "LinkProductVariantPriceSet"
|
||||
variant_id: Scalars["String"]["output"]
|
||||
price_set_id: Scalars["String"]["output"]
|
||||
variant?: Maybe<Product>
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkPublishableApiKeySalesChannel = {
|
||||
__typename?: "LinkPublishableApiKeySalesChannel"
|
||||
publishable_key_id: Scalars["String"]["output"]
|
||||
sales_channel_id: Scalars["String"]["output"]
|
||||
sales_channel?: Maybe<SalesChannel>
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkRegionPaymentProvider = {
|
||||
__typename?: "LinkRegionPaymentProvider"
|
||||
region_id: Scalars["String"]["output"]
|
||||
payment_provider_id: Scalars["String"]["output"]
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkSalesChannelStockLocation = {
|
||||
__typename?: "LinkSalesChannelStockLocation"
|
||||
sales_channel_id: Scalars["String"]["output"]
|
||||
stock_location_id: Scalars["String"]["output"]
|
||||
sales_channel?: Maybe<SalesChannel>
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export type LinkShippingOptionPriceSet = {
|
||||
__typename?: "LinkShippingOptionPriceSet"
|
||||
shipping_option_id: Scalars["String"]["output"]
|
||||
price_set_id: Scalars["String"]["output"]
|
||||
createdAt: Scalars["String"]["output"]
|
||||
updatedAt: Scalars["String"]["output"]
|
||||
deletedAt?: Maybe<Scalars["String"]["output"]>
|
||||
}
|
||||
|
||||
export interface FixtureEntryPoints {
|
||||
file: any
|
||||
files: any
|
||||
workflow_execution: any
|
||||
workflow_executions: any
|
||||
inventory_items: any
|
||||
inventory_item: any
|
||||
inventory: any
|
||||
reservation: any
|
||||
reservations: any
|
||||
reservation_item: any
|
||||
reservation_items: any
|
||||
inventory_level: any
|
||||
inventory_levels: any
|
||||
stock_location_address: any
|
||||
stock_location_addresses: any
|
||||
stock_location: any
|
||||
stock_locations: any
|
||||
price_set: any
|
||||
price_sets: any
|
||||
price_list: any
|
||||
price_lists: any
|
||||
price: any
|
||||
prices: any
|
||||
price_preference: any
|
||||
price_preferences: any
|
||||
product_variant: ProductVariant
|
||||
product_variants: ProductVariant
|
||||
variant: ProductVariant
|
||||
variants: ProductVariant
|
||||
product: Product
|
||||
products: Product
|
||||
simple_product: SimpleProduct
|
||||
product_option: any
|
||||
product_options: any
|
||||
product_type: any
|
||||
product_types: any
|
||||
product_image: any
|
||||
product_images: any
|
||||
product_tag: any
|
||||
product_tags: any
|
||||
product_collection: any
|
||||
product_collections: any
|
||||
product_category: ProductCategory
|
||||
product_categories: ProductCategory
|
||||
sales_channel: SalesChannel
|
||||
sales_channels: SalesChannel
|
||||
customer_address: any
|
||||
customer_addresses: any
|
||||
customer_group_customer: any
|
||||
customer_group_customers: any
|
||||
customer_group: any
|
||||
customer_groups: any
|
||||
customer: any
|
||||
customers: any
|
||||
cart: any
|
||||
carts: any
|
||||
address: any
|
||||
addresses: any
|
||||
line_item: any
|
||||
line_items: any
|
||||
line_item_adjustment: any
|
||||
line_item_adjustments: any
|
||||
line_item_tax_line: any
|
||||
line_item_tax_lines: any
|
||||
shipping_method: any
|
||||
shipping_methods: any
|
||||
shipping_method_adjustment: any
|
||||
shipping_method_adjustments: any
|
||||
shipping_method_tax_line: any
|
||||
shipping_method_tax_lines: any
|
||||
promotion: any
|
||||
promotions: any
|
||||
campaign: any
|
||||
campaigns: any
|
||||
promotion_rule: any
|
||||
promotion_rules: any
|
||||
api_key: any
|
||||
api_keys: any
|
||||
tax_rate: any
|
||||
tax_rates: any
|
||||
tax_region: any
|
||||
tax_regions: any
|
||||
tax_rate_rule: any
|
||||
tax_rate_rules: any
|
||||
tax_provider: any
|
||||
tax_providers: any
|
||||
store: any
|
||||
stores: any
|
||||
store_currency: any
|
||||
store_currencies: any
|
||||
user: any
|
||||
users: any
|
||||
invite: any
|
||||
invites: any
|
||||
auth_identity: any
|
||||
auth_identities: any
|
||||
order: any
|
||||
orders: any
|
||||
order_address: any
|
||||
order_addresses: any
|
||||
order_line_item: any
|
||||
order_line_items: any
|
||||
order_line_item_adjustment: any
|
||||
order_line_item_adjustments: any
|
||||
order_line_item_tax_line: any
|
||||
order_line_item_tax_lines: any
|
||||
order_shipping_method: any
|
||||
order_shipping_methods: any
|
||||
order_shipping_method_adjustment: any
|
||||
order_shipping_method_adjustments: any
|
||||
order_shipping_method_tax_line: any
|
||||
order_shipping_method_tax_lines: any
|
||||
order_transaction: any
|
||||
order_transactions: any
|
||||
order_change: any
|
||||
order_changes: any
|
||||
order_change_action: any
|
||||
order_change_actions: any
|
||||
order_item: any
|
||||
order_items: any
|
||||
order_summary: any
|
||||
order_summaries: any
|
||||
order_shipping: any
|
||||
order_shippings: any
|
||||
return_reason: any
|
||||
return_reasons: any
|
||||
return: any
|
||||
returns: any
|
||||
return_item: any
|
||||
return_items: any
|
||||
order_claim: any
|
||||
order_claims: any
|
||||
order_claim_item: any
|
||||
order_claim_items: any
|
||||
order_claim_item_image: any
|
||||
order_claim_item_images: any
|
||||
order_exchange: any
|
||||
order_exchanges: any
|
||||
order_exchange_item: any
|
||||
order_exchange_items: any
|
||||
payment: any
|
||||
payments: any
|
||||
payment_collection: any
|
||||
payment_collections: any
|
||||
payment_provider: any
|
||||
payment_providers: any
|
||||
payment_session: any
|
||||
payment_sessions: any
|
||||
refund_reason: any
|
||||
refund_reasons: any
|
||||
fulfillment_address: any
|
||||
fulfillment_addresses: any
|
||||
fulfillment_item: any
|
||||
fulfillment_items: any
|
||||
fulfillment_label: any
|
||||
fulfillment_labels: any
|
||||
fulfillment_provider: any
|
||||
fulfillment_providers: any
|
||||
fulfillment_set: any
|
||||
fulfillment_sets: any
|
||||
fulfillment: any
|
||||
fulfillments: any
|
||||
geo_zone: any
|
||||
geo_zones: any
|
||||
service_zone: any
|
||||
service_zones: any
|
||||
shipping_option_rule: any
|
||||
shipping_option_rules: any
|
||||
shipping_option_type: any
|
||||
shipping_option_types: any
|
||||
shipping_option: any
|
||||
shipping_options: any
|
||||
shipping_profile: any
|
||||
shipping_profiles: any
|
||||
notification: any
|
||||
notifications: any
|
||||
region: any
|
||||
regions: any
|
||||
country: any
|
||||
countries: any
|
||||
currency: any
|
||||
currencies: any
|
||||
cart_payment_collection: LinkCartPaymentCollection
|
||||
cart_payment_collections: LinkCartPaymentCollection
|
||||
cart_promotion: LinkCartPromotion
|
||||
cart_promotions: LinkCartPromotion
|
||||
location_fulfillment_provider: LinkLocationFulfillmentProvider
|
||||
location_fulfillment_providers: LinkLocationFulfillmentProvider
|
||||
location_fulfillment_set: LinkLocationFulfillmentSet
|
||||
location_fulfillment_sets: LinkLocationFulfillmentSet
|
||||
order_cart: LinkOrderCart
|
||||
order_carts: LinkOrderCart
|
||||
order_fulfillment: LinkOrderFulfillment
|
||||
order_fulfillments: LinkOrderFulfillment
|
||||
order_payment_collection: LinkOrderPaymentCollection
|
||||
order_payment_collections: LinkOrderPaymentCollection
|
||||
order_promotion: LinkOrderPromotion
|
||||
order_promotions: LinkOrderPromotion
|
||||
return_fulfillment: LinkReturnFulfillment
|
||||
return_fulfillments: LinkReturnFulfillment
|
||||
product_sales_channel: LinkProductSalesChannel
|
||||
product_sales_channels: LinkProductSalesChannel
|
||||
product_variant_inventory_item: LinkProductVariantInventoryItem
|
||||
product_variant_inventory_items: LinkProductVariantInventoryItem
|
||||
product_variant_price_set: LinkProductVariantPriceSet
|
||||
product_variant_price_sets: LinkProductVariantPriceSet
|
||||
publishable_api_key_sales_channel: LinkPublishableApiKeySalesChannel
|
||||
publishable_api_key_sales_channels: LinkPublishableApiKeySalesChannel
|
||||
region_payment_provider: LinkRegionPaymentProvider
|
||||
region_payment_providers: LinkRegionPaymentProvider
|
||||
sales_channel_location: LinkSalesChannelStockLocation
|
||||
sales_channel_locations: LinkSalesChannelStockLocation
|
||||
shipping_option_price_set: LinkShippingOptionPriceSet
|
||||
shipping_option_price_sets: LinkShippingOptionPriceSet
|
||||
}
|
||||
|
||||
declare module "../remote-query-entry-points" {
|
||||
export interface RemoteQueryEntryPoints extends FixtureEntryPoints {}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
import { ObjectToRemoteQueryFields } from "../object-to-remote-query-fields"
|
||||
import { expectTypeOf } from "expect-type"
|
||||
|
||||
describe("ObjectToRemoteQueryFields", () => {
|
||||
it("should return all the nested paths properties from an object", () => {
|
||||
type Object = {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
date: Date
|
||||
variants: {
|
||||
id: string
|
||||
sku: string
|
||||
title: string
|
||||
}[]
|
||||
sales_channel: {
|
||||
id: string
|
||||
name: string
|
||||
value: string
|
||||
}
|
||||
metadata: Record<string, unknown>
|
||||
}
|
||||
|
||||
type Paths = ObjectToRemoteQueryFields<Object>
|
||||
|
||||
expectTypeOf<Paths>().toEqualTypeOf<
|
||||
| "*"
|
||||
| "date"
|
||||
| "metadata"
|
||||
| "id"
|
||||
| "title"
|
||||
| "description"
|
||||
| "variants.*"
|
||||
| "variants.id"
|
||||
| "variants.sku"
|
||||
| "variants.title"
|
||||
| "sales_channel.*"
|
||||
| "sales_channel.id"
|
||||
| "sales_channel.name"
|
||||
| "sales_channel.value"
|
||||
>()
|
||||
})
|
||||
|
||||
it("should return all the nested paths properties from an object with nullable and undefined", () => {
|
||||
type Maybe<T> = T | null
|
||||
|
||||
type Object = {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
date: Date
|
||||
variants: Maybe<
|
||||
Maybe<{
|
||||
id: string
|
||||
sku: string
|
||||
title: string
|
||||
}>[]
|
||||
>
|
||||
sales_channel?: Maybe<{
|
||||
id: string
|
||||
name: string
|
||||
value: string
|
||||
}>
|
||||
metadata: Record<string, unknown>
|
||||
}
|
||||
|
||||
type Paths = ObjectToRemoteQueryFields<Object>
|
||||
|
||||
expectTypeOf<Paths>().toEqualTypeOf<
|
||||
| "*"
|
||||
| "id"
|
||||
| "metadata"
|
||||
| "date"
|
||||
| "title"
|
||||
| "description"
|
||||
| "variants.*"
|
||||
| "variants.id"
|
||||
| "variants.sku"
|
||||
| "variants.title"
|
||||
| "sales_channel.*"
|
||||
| "sales_channel.id"
|
||||
| "sales_channel.name"
|
||||
| "sales_channel.value"
|
||||
>()
|
||||
})
|
||||
|
||||
it("should fail return all the nested paths properties from an object with nullable and undefined", () => {
|
||||
type Maybe<T> = T | null
|
||||
|
||||
type Object = {
|
||||
id: string
|
||||
title: string
|
||||
description: string
|
||||
date: Date
|
||||
variants: Maybe<
|
||||
Maybe<{
|
||||
id: string
|
||||
sku: string
|
||||
title: string
|
||||
}>[]
|
||||
>
|
||||
sales_channel?: Maybe<{
|
||||
id: string
|
||||
name: string
|
||||
value: string
|
||||
}>
|
||||
metadata: Record<string, unknown>
|
||||
}
|
||||
|
||||
type Paths = ObjectToRemoteQueryFields<Object>
|
||||
|
||||
expectTypeOf<Paths>().toEqualTypeOf<
|
||||
// @ts-expect-error
|
||||
| "foo"
|
||||
| "*"
|
||||
| "date"
|
||||
| "metadata"
|
||||
| "id"
|
||||
| "title"
|
||||
| "description"
|
||||
| "variants.*"
|
||||
| "variants.id"
|
||||
| "variants.sku"
|
||||
| "variants.title"
|
||||
| "sales_channel.*"
|
||||
| "sales_channel.id"
|
||||
| "sales_channel.name"
|
||||
| "sales_channel.value"
|
||||
>()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,56 @@
|
||||
import { expectTypeOf } from "expect-type"
|
||||
import { RemoteQueryEntryPoints } from "../remote-query-entry-points"
|
||||
import { FixtureEntryPoints } from "../__fixtures__/remote-query"
|
||||
import { RemoteQueryObjectConfig } from "../remote-query-object-from-string"
|
||||
|
||||
describe("RemoteQuery", () => {
|
||||
describe("RemoteQueryEntryPoints", () => {
|
||||
it("should include declaration merging types with the defined entry points", () => {
|
||||
expectTypeOf<RemoteQueryEntryPoints>().toMatchTypeOf<FixtureEntryPoints>()
|
||||
})
|
||||
})
|
||||
|
||||
describe("RemoteQueryObjectConfig", () => {
|
||||
it("should return the correct type for fields when using a string entry point", () => {
|
||||
type Result = RemoteQueryObjectConfig<"simple_product">["fields"]
|
||||
expectTypeOf<Result>().toEqualTypeOf<
|
||||
(
|
||||
| "*"
|
||||
| "id"
|
||||
| "handle"
|
||||
| "title"
|
||||
| "variants.id"
|
||||
| "variants.*"
|
||||
| "sales_channels.id"
|
||||
| "sales_channels.*"
|
||||
| "sales_channels.name"
|
||||
| "sales_channels_link.*"
|
||||
| "sales_channels_link.product_id"
|
||||
| "sales_channels_link.sales_channel_id"
|
||||
)[]
|
||||
>()
|
||||
})
|
||||
|
||||
it("should fail return the correct type for fields when using a string entry point", () => {
|
||||
type Result = RemoteQueryObjectConfig<"simple_product">["fields"]
|
||||
expectTypeOf<Result>().toEqualTypeOf<
|
||||
// @ts-expect-error
|
||||
(
|
||||
| "*"
|
||||
| "foo"
|
||||
| "id"
|
||||
| "handle"
|
||||
| "title"
|
||||
| "variants.id"
|
||||
| "variants.*"
|
||||
| "sales_channels.id"
|
||||
| "sales_channels.*"
|
||||
| "sales_channels.name"
|
||||
| "sales_channels_link.*"
|
||||
| "sales_channels_link.product_id"
|
||||
| "sales_channels_link.sales_channel_id"
|
||||
)[]
|
||||
>()
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,19 +1,22 @@
|
||||
import {
|
||||
JoinerRelationship,
|
||||
JoinerServiceConfig,
|
||||
RemoteJoinerOptions,
|
||||
RemoteJoinerQuery,
|
||||
} from "../joiner"
|
||||
import { JoinerRelationship, JoinerServiceConfig } from "../joiner"
|
||||
|
||||
import { MedusaContainer } from "../common"
|
||||
import { RepositoryService } from "../dal"
|
||||
import { Logger } from "../logger"
|
||||
import {
|
||||
RemoteQueryObjectConfig,
|
||||
RemoteQueryObjectFromStringResult,
|
||||
} from "./remote-query-object-from-string"
|
||||
|
||||
export { RemoteQueryObjectConfig, RemoteQueryObjectFromStringResult }
|
||||
|
||||
export type Constructor<T> = new (...args: any[]) => T | (new () => T)
|
||||
|
||||
export * from "../common/medusa-container"
|
||||
export * from "./medusa-internal-service"
|
||||
export * from "./module-provider"
|
||||
export * from "./remote-query"
|
||||
export * from "./remote-query-entry-points"
|
||||
|
||||
export type LogLevel =
|
||||
| "query"
|
||||
@@ -292,12 +295,6 @@ export type ModuleBootstrapDeclaration =
|
||||
// | ModuleServiceInitializeOptions
|
||||
// | ModuleServiceInitializeCustomDataLayerOptions
|
||||
|
||||
export type RemoteQueryFunction = (
|
||||
query: string | RemoteJoinerQuery | object,
|
||||
variables?: Record<string, unknown>,
|
||||
options?: RemoteJoinerOptions
|
||||
) => Promise<any> | null
|
||||
|
||||
export interface IModuleService {
|
||||
/**
|
||||
* @ignore
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
type Marker = [never, 0, 1, 2, 3, 4]
|
||||
|
||||
type ExcludedProps = ["__typename"]
|
||||
type SpecialNonRelationProps = ["metadata"]
|
||||
type RawBigNumberPrefix = "raw_"
|
||||
|
||||
type ExpandStarSelector<
|
||||
T extends object,
|
||||
Depth extends number,
|
||||
Exclusion extends string[]
|
||||
> = ObjectToRemoteQueryFields<T & { "*": "*" }, Depth, Exclusion>
|
||||
|
||||
type TypeOnly<T> = Required<Exclude<T, null | undefined>>
|
||||
|
||||
/**
|
||||
* Output an array of strings representing the path to each leaf node in an object
|
||||
*/
|
||||
export type ObjectToRemoteQueryFields<
|
||||
MaybeT,
|
||||
Depth extends number = 2,
|
||||
Exclusion extends string[] = [],
|
||||
T = TypeOnly<MaybeT> & { "*": "*" }
|
||||
> = Depth extends never
|
||||
? never
|
||||
: T extends object
|
||||
? {
|
||||
[K in keyof T]: K extends // handle big number
|
||||
`${RawBigNumberPrefix}${string}`
|
||||
? Exclude<K, symbol>
|
||||
: // handle metadata
|
||||
K extends SpecialNonRelationProps[number]
|
||||
? Exclude<K, symbol>
|
||||
: // Special props that should be excluded
|
||||
K extends ExcludedProps[number]
|
||||
? never
|
||||
: // Prevent recursive reference to itself
|
||||
K extends Exclusion[number]
|
||||
? never
|
||||
: TypeOnly<T[K]> extends Array<infer R>
|
||||
? TypeOnly<R> extends Date
|
||||
? Exclude<K, symbol>
|
||||
: TypeOnly<R> extends object
|
||||
? `${Exclude<K, symbol>}.${ExpandStarSelector<
|
||||
TypeOnly<R>,
|
||||
Marker[Depth],
|
||||
[K & string, ...Exclusion]
|
||||
>}`
|
||||
: never
|
||||
: TypeOnly<T[K]> extends Date
|
||||
? Exclude<K, symbol>
|
||||
: TypeOnly<T[K]> extends object
|
||||
? `${Exclude<K, symbol>}.${ExpandStarSelector<
|
||||
TypeOnly<T[K]>,
|
||||
Marker[Depth],
|
||||
[K & string, ...Exclusion]
|
||||
>}`
|
||||
: Exclude<K, symbol>
|
||||
}[keyof T]
|
||||
: never
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Bucket filled with map of entry point -> types that are autogenerated by the CLI
|
||||
*/
|
||||
export interface RemoteQueryEntryPoints {}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { RemoteQueryEntryPoints } from "./remote-query-entry-points"
|
||||
import { ObjectToRemoteQueryFields } from "./object-to-remote-query-fields"
|
||||
|
||||
export type RemoteQueryObjectConfig<TEntry extends string> = {
|
||||
// service: string This property is still supported under the hood but part of the type due to types missmatch towards fields
|
||||
entryPoint: TEntry | keyof RemoteQueryEntryPoints
|
||||
variables?: any
|
||||
fields: ObjectToRemoteQueryFields<
|
||||
RemoteQueryEntryPoints[TEntry & keyof RemoteQueryEntryPoints]
|
||||
> extends never
|
||||
? string[]
|
||||
: ObjectToRemoteQueryFields<
|
||||
RemoteQueryEntryPoints[TEntry & keyof RemoteQueryEntryPoints]
|
||||
>[]
|
||||
}
|
||||
|
||||
export type RemoteQueryObjectFromStringResult<
|
||||
TConfig extends RemoteQueryObjectConfig<any>
|
||||
> = {
|
||||
__TConfig: TConfig
|
||||
__value: object
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import { RemoteJoinerOptions, RemoteJoinerQuery } from "../joiner"
|
||||
import {
|
||||
RemoteQueryObjectConfig,
|
||||
RemoteQueryObjectFromStringResult,
|
||||
} from "./remote-query-object-from-string"
|
||||
|
||||
/*type ExcludedProps = "__typename"*/
|
||||
|
||||
export type RemoteQueryFunctionReturnPagination = {
|
||||
skip: number
|
||||
take: number
|
||||
count: number
|
||||
}
|
||||
|
||||
/*export type RemoteQueryReturnedData<TEntry extends string> =
|
||||
TEntry extends keyof RemoteQueryEntryPoints
|
||||
? Prettify<Omit<RemoteQueryEntryPoints[TEntry], ExcludedProps>>
|
||||
: any*/
|
||||
|
||||
/*export type NarrowRemoteFunctionReturnType<
|
||||
TConfig extends RemoteQueryObjectConfig<any>
|
||||
> = TConfig extends RemoteQueryObjectConfig<infer TEntry>
|
||||
? TConfig extends { variables: infer Variables }
|
||||
? Variables extends { skip: number }
|
||||
? {
|
||||
rows: RemoteQueryReturnedData<TEntry>[]
|
||||
metadata: RemoteQueryFunctionReturnPagination
|
||||
}
|
||||
: Variables extends { skip?: number | undefined } | { skip?: number }
|
||||
? // TODO: the real type is the one in parenthsis but we put any for now as the current API is broken and need fixin in a separate iteration (RemoteQueryReturnedData<TEntry>[] | {rows: RemoteQueryReturnedData<TEntry>[] metadata: RemoteQueryFunctionReturnPagination })
|
||||
any
|
||||
: RemoteQueryReturnedData<TEntry>[]
|
||||
: RemoteQueryReturnedData<TEntry>[]
|
||||
: never*/
|
||||
|
||||
/*export type RemoteQueryFunctionReturnType<
|
||||
TConfig extends
|
||||
| RemoteQueryObjectConfig<any>
|
||||
| RemoteQueryObjectFromStringResult<any>
|
||||
> = TConfig extends RemoteQueryObjectFromStringResult<any>
|
||||
? NarrowRemoteFunctionReturnType<TConfig['__value']>
|
||||
: TConfig extends RemoteQueryObjectConfig<any>
|
||||
? NarrowRemoteFunctionReturnType<TConfig>
|
||||
: never*/
|
||||
|
||||
export type RemoteQueryFunction = {
|
||||
/**
|
||||
* Query wrapper to provide specific API's and pre processing around remoteQuery.query
|
||||
* @param queryConfig
|
||||
* @param options
|
||||
*/
|
||||
<const TEntry extends string>(
|
||||
queryConfig: RemoteQueryObjectConfig<TEntry>,
|
||||
options?: RemoteJoinerOptions
|
||||
): Promise<any>
|
||||
|
||||
/**
|
||||
* Query wrapper to provide specific API's and pre processing around remoteQuery.query
|
||||
* @param queryConfig
|
||||
* @param options
|
||||
*/
|
||||
<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
|
||||
*/
|
||||
(query: RemoteJoinerQuery, options?: RemoteJoinerOptions): Promise<any>
|
||||
/**
|
||||
* Query wrapper to provide specific GraphQL like API around remoteQuery.query
|
||||
* @param query
|
||||
* @param variables
|
||||
* @param options
|
||||
*/
|
||||
gql: (
|
||||
query: string,
|
||||
variables?: Record<string, unknown>,
|
||||
options?: RemoteJoinerOptions
|
||||
) => Promise<any>
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["src"],
|
||||
"exclude": [
|
||||
"dist",
|
||||
"src/**/__tests__",
|
||||
"src/**/__mocks__",
|
||||
"src/**/__fixtures__",
|
||||
"node_modules"
|
||||
],
|
||||
}
|
||||
@@ -21,8 +21,6 @@
|
||||
"include": ["src"],
|
||||
"exclude": [
|
||||
"dist",
|
||||
"./src/**/__tests__",
|
||||
"./src/**/__mocks__",
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"include": ["src", "integration-tests"],
|
||||
"exclude": ["node_modules", "dist"],
|
||||
"compilerOptions": {
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import { deepMerge } from "../deep-merge"
|
||||
|
||||
describe("Deep merge ", function () {
|
||||
it("should merge 2 objects", () => {
|
||||
const a = {
|
||||
x: 1,
|
||||
y: {
|
||||
z: 3,
|
||||
w: 4,
|
||||
a: {
|
||||
b: 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
const aCopy = JSON.parse(JSON.stringify(a))
|
||||
|
||||
const b = {
|
||||
y: {
|
||||
w: 5,
|
||||
q: 6,
|
||||
a: {
|
||||
c: 14,
|
||||
},
|
||||
},
|
||||
z: 2,
|
||||
}
|
||||
const bCopy = JSON.parse(JSON.stringify(b))
|
||||
|
||||
const merged = deepMerge(a, b)
|
||||
expect(merged).toEqual({
|
||||
x: 1,
|
||||
y: {
|
||||
z: 3,
|
||||
w: 5,
|
||||
a: {
|
||||
b: 1,
|
||||
c: 14,
|
||||
},
|
||||
q: 6,
|
||||
},
|
||||
z: 2,
|
||||
})
|
||||
expect(a).toEqual(aCopy)
|
||||
expect(b).toEqual(bCopy)
|
||||
})
|
||||
})
|
||||
@@ -45,7 +45,7 @@ describe("remoteQueryObjectFromString", function () {
|
||||
fields,
|
||||
})
|
||||
|
||||
expect(output).toEqual({
|
||||
expect(output.__value).toEqual({
|
||||
product: {
|
||||
__args: {
|
||||
q: "name",
|
||||
@@ -101,9 +101,9 @@ describe("remoteQueryObjectFromString", function () {
|
||||
service: "product",
|
||||
variables: {},
|
||||
fields,
|
||||
})
|
||||
} as any)
|
||||
|
||||
expect(output).toEqual({
|
||||
expect(output.__value).toEqual({
|
||||
product: {
|
||||
__args: {},
|
||||
fields: [
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import { isObject } from "./is-object"
|
||||
|
||||
export function deepMerge(target: any, source: any) {
|
||||
const recursive = (a, b) => {
|
||||
if (!isObject(a)) {
|
||||
return b
|
||||
}
|
||||
if (!isObject(b)) {
|
||||
return a
|
||||
}
|
||||
|
||||
Object.keys(b).forEach((key) => {
|
||||
if (isObject(b[key])) {
|
||||
a[key] ??= {}
|
||||
a[key] = deepMerge(a[key], b[key])
|
||||
} else {
|
||||
a[key] = b[key]
|
||||
}
|
||||
})
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
const copy = { ...target }
|
||||
return recursive(copy, source)
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { MapToConfig } from "./map-object-to"
|
||||
|
||||
export function generateLinkableKeysMap(
|
||||
linkableKeys: Record<string, string>
|
||||
): MapToConfig {
|
||||
const entityLinkableKeysMap: MapToConfig = {}
|
||||
|
||||
Object.entries(linkableKeys).forEach(([key, value]) => {
|
||||
entityLinkableKeysMap[value] ??= []
|
||||
entityLinkableKeysMap[value].push({
|
||||
mapTo: key,
|
||||
valueFrom: key.split("_").pop()!,
|
||||
})
|
||||
})
|
||||
|
||||
return entityLinkableKeysMap
|
||||
}
|
||||
@@ -12,10 +12,12 @@ export * from "./deduplicate"
|
||||
export * from "./deep-copy"
|
||||
export * from "./deep-equal-obj"
|
||||
export * from "./deep-flat-map"
|
||||
export * from "./deep-merge"
|
||||
export * from "./define-config"
|
||||
export * from "./env-editor"
|
||||
export * from "./errors"
|
||||
export * from "./file-system"
|
||||
export * from "./generate-entity-id"
|
||||
export * from "./generate-linkable-keys-map"
|
||||
export * from "./get-caller-file-path"
|
||||
export * from "./get-config-file"
|
||||
export * from "./get-duplicates"
|
||||
@@ -26,7 +28,6 @@ export * from "./get-set-difference"
|
||||
export * from "./graceful-shutdown-server"
|
||||
export * from "./group-by"
|
||||
export * from "./handle-postgres-database-error"
|
||||
export * from "./is-truthy"
|
||||
export * from "./is-big-number"
|
||||
export * from "./is-boolean"
|
||||
export * from "./is-date"
|
||||
@@ -35,10 +36,12 @@ export * from "./is-email"
|
||||
export * from "./is-object"
|
||||
export * from "./is-present"
|
||||
export * from "./is-string"
|
||||
export * from "./is-truthy"
|
||||
export * from "./load-env"
|
||||
export * from "./lower-case-first"
|
||||
export * from "./map-object-to"
|
||||
export * from "./medusa-container"
|
||||
export * from "./normalize-import-path-with-source"
|
||||
export * from "./object-from-string-path"
|
||||
export * from "./object-to-string-path"
|
||||
export * from "./optional-numeric-serializer"
|
||||
@@ -68,6 +71,3 @@ export * from "./trim-zeros"
|
||||
export * from "./upper-case-first"
|
||||
export * from "./validate-handle"
|
||||
export * from "./wrap-handler"
|
||||
export * from "./define-config"
|
||||
export * from "./env-editor"
|
||||
export * from "./normalize-import-path-with-source"
|
||||
@@ -1,3 +1,7 @@
|
||||
import {
|
||||
RemoteQueryObjectConfig,
|
||||
RemoteQueryObjectFromStringResult,
|
||||
} from "@medusajs/types"
|
||||
import { isObject } from "./is-object"
|
||||
|
||||
/**
|
||||
@@ -83,20 +87,18 @@ import { isObject } from "./is-object"
|
||||
* // },
|
||||
* // }
|
||||
*/
|
||||
export function remoteQueryObjectFromString(
|
||||
config:
|
||||
| {
|
||||
entryPoint: string
|
||||
variables?: any
|
||||
fields: string[]
|
||||
}
|
||||
| {
|
||||
service: string
|
||||
variables?: any
|
||||
fields: string[]
|
||||
}
|
||||
): object {
|
||||
const { entryPoint, service, variables, fields } = {
|
||||
export function remoteQueryObjectFromString<
|
||||
const TEntry extends string,
|
||||
const TConfig extends RemoteQueryObjectConfig<TEntry>
|
||||
>(
|
||||
config: TConfig | RemoteQueryObjectConfig<TEntry>
|
||||
): RemoteQueryObjectFromStringResult<TConfig> {
|
||||
const {
|
||||
entryPoint,
|
||||
service,
|
||||
variables = {},
|
||||
fields = [],
|
||||
} = {
|
||||
...config,
|
||||
entryPoint: "entryPoint" in config ? config.entryPoint : undefined,
|
||||
service: "service" in config ? config.service : undefined,
|
||||
@@ -114,12 +116,13 @@ export function remoteQueryObjectFromString(
|
||||
const usedVariables = new Set()
|
||||
|
||||
for (const field of fields) {
|
||||
if (!field.includes(".")) {
|
||||
const fieldAsString = field as string
|
||||
if (!fieldAsString.includes(".")) {
|
||||
remoteJoinerConfig[entryKey]["fields"].push(field)
|
||||
continue
|
||||
}
|
||||
|
||||
const fieldSegments = field.split(".")
|
||||
const fieldSegments = fieldAsString.split(".")
|
||||
const fieldProperty = fieldSegments.pop()
|
||||
|
||||
let combinedPath = ""
|
||||
@@ -151,5 +154,7 @@ export function remoteQueryObjectFromString(
|
||||
|
||||
remoteJoinerConfig[entryKey]["__args"] = topLevelArgs ?? {}
|
||||
|
||||
return remoteJoinerConfig
|
||||
return {
|
||||
__value: remoteJoinerConfig,
|
||||
} as RemoteQueryObjectFromStringResult<TConfig>
|
||||
}
|
||||
@@ -51,7 +51,7 @@ export function defineJoinerConfig(
|
||||
alias?: JoinerServiceConfigAlias[]
|
||||
schema?: string
|
||||
models?: DmlEntity<any, any>[] | { name: string }[]
|
||||
linkableKeys?: Record<string, string>
|
||||
linkableKeys?: ModuleJoinerConfig["linkableKeys"]
|
||||
primaryKeys?: string[]
|
||||
} = {}
|
||||
): Omit<
|
||||
@@ -151,18 +151,19 @@ export function defineJoinerConfig(
|
||||
schema = toGraphQLSchema([...modelDefinitions.values()])
|
||||
}
|
||||
|
||||
if (!linkableKeys) {
|
||||
const linkableKeysFromDml = buildLinkableKeysFromDmlObjects([
|
||||
...modelDefinitions.values(),
|
||||
])
|
||||
const linkableKeysFromMikroOrm = buildLinkableKeysFromMikroOrmObjects([
|
||||
...mikroOrmObjects.values(),
|
||||
])
|
||||
linkableKeys = {
|
||||
|
||||
const mergedLinkableKeys = {
|
||||
...linkableKeysFromDml,
|
||||
...linkableKeysFromMikroOrm,
|
||||
...linkableKeys,
|
||||
}
|
||||
}
|
||||
linkableKeys = mergedLinkableKeys
|
||||
|
||||
if (!primaryKeys && modelDefinitions.size) {
|
||||
const linkConfig = buildLinkConfigFromModelObjects(
|
||||
@@ -370,6 +371,7 @@ export function buildLinkConfigFromModelObjects<
|
||||
const linkableKeyName =
|
||||
parsedProperty.dataType.options?.linkable ??
|
||||
`${camelToSnakeCase(model.name).toLowerCase()}_${property}`
|
||||
|
||||
modelLinkConfig[property] = {
|
||||
linkable: linkableKeyName,
|
||||
primaryKey: property,
|
||||
@@ -397,21 +399,24 @@ export function buildLinkConfigFromLinkableKeys<
|
||||
|
||||
for (const [linkable, modelName] of Object.entries(linkableKeys)) {
|
||||
const kebabCasedModelName = camelToSnakeCase(toCamelCase(modelName))
|
||||
|
||||
const inferredReferenceProperty = linkable.replace(
|
||||
`${kebabCasedModelName}_`,
|
||||
""
|
||||
)
|
||||
|
||||
const keyName = lowerCaseFirst(modelName)
|
||||
const config = {
|
||||
linkable: linkable,
|
||||
primaryKey: inferredReferenceProperty,
|
||||
serviceName,
|
||||
field: lowerCaseFirst(modelName),
|
||||
field: keyName,
|
||||
}
|
||||
linkConfig[lowerCaseFirst(modelName)] = {
|
||||
[inferredReferenceProperty]: config,
|
||||
|
||||
linkConfig[keyName] ??= {
|
||||
toJSON: () => config,
|
||||
}
|
||||
linkConfig[keyName][inferredReferenceProperty] = config
|
||||
}
|
||||
|
||||
return linkConfig as Record<string, any>
|
||||
@@ -432,6 +437,5 @@ export function buildModelsNameToLinkableKeysMap(
|
||||
valueFrom: key.split("_").pop()!,
|
||||
})
|
||||
})
|
||||
|
||||
return entityLinkableKeysMap
|
||||
}
|
||||
@@ -35,12 +35,12 @@ export function Module<
|
||||
} {
|
||||
const modelObjects = service[MedusaServiceModelObjectsSymbol] ?? {}
|
||||
|
||||
const defaultJoinerConfig = defineJoinerConfig(serviceName, {
|
||||
service.prototype.__joinerConfig ??= () =>
|
||||
defineJoinerConfig(serviceName, {
|
||||
models: Object.keys(modelObjects).length
|
||||
? Object.values(modelObjects)
|
||||
: undefined,
|
||||
})
|
||||
service.prototype.__joinerConfig ??= () => defaultJoinerConfig
|
||||
|
||||
let linkable = {} as Linkable
|
||||
|
||||
|
||||
@@ -11,3 +11,5 @@ export * from "./subscribers"
|
||||
export * from "./workflows"
|
||||
|
||||
export const MEDUSA_CLI_PATH = require.resolve("@medusajs/medusa-cli")
|
||||
|
||||
export { GraphQLSchema, gqlSchemaToTypes } from "@medusajs/modules-sdk"
|
||||
@@ -31,7 +31,6 @@ export const POST = async (
|
||||
},
|
||||
fields: ["return_id"],
|
||||
}),
|
||||
undefined,
|
||||
{
|
||||
throwIfKeyNotFound: true,
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ export const POST = async (
|
||||
},
|
||||
fields: ["return_id"],
|
||||
}),
|
||||
undefined,
|
||||
{
|
||||
throwIfKeyNotFound: true,
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@ export const POST = async (
|
||||
},
|
||||
fields: ["return_id"],
|
||||
}),
|
||||
undefined,
|
||||
{
|
||||
throwIfKeyNotFound: true,
|
||||
}
|
||||
@@ -79,7 +78,6 @@ export const DELETE = async (
|
||||
},
|
||||
fields: ["id", "return_id"],
|
||||
}),
|
||||
undefined,
|
||||
{
|
||||
throwIfKeyNotFound: true,
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ export const POST = async (
|
||||
},
|
||||
fields: ["return_id"],
|
||||
}),
|
||||
undefined,
|
||||
{
|
||||
throwIfKeyNotFound: true,
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export const POST = async (
|
||||
fields: req.remoteQueryConfig.fields,
|
||||
})
|
||||
|
||||
const [orderClaim] = await remoteQuery(queryObject, undefined, {
|
||||
const [orderClaim] = await remoteQuery(queryObject, {
|
||||
throwIfKeyNotFound: true,
|
||||
})
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ export const POST = async (
|
||||
},
|
||||
fields: ["return_id"],
|
||||
}),
|
||||
undefined,
|
||||
{
|
||||
throwIfKeyNotFound: true,
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ export const POST = async (
|
||||
},
|
||||
fields: ["return_id"],
|
||||
}),
|
||||
undefined,
|
||||
{
|
||||
throwIfKeyNotFound: true,
|
||||
}
|
||||
|
||||
-2
@@ -30,7 +30,6 @@ export const POST = async (
|
||||
},
|
||||
fields: ["return_id"],
|
||||
}),
|
||||
undefined,
|
||||
{
|
||||
throwIfKeyNotFound: true,
|
||||
}
|
||||
@@ -79,7 +78,6 @@ export const DELETE = async (
|
||||
},
|
||||
fields: ["return_id"],
|
||||
}),
|
||||
undefined,
|
||||
{
|
||||
throwIfKeyNotFound: true,
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ export const POST = async (
|
||||
},
|
||||
fields: ["return_id"],
|
||||
}),
|
||||
undefined,
|
||||
{
|
||||
throwIfKeyNotFound: true,
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ export const POST = async (
|
||||
fields: req.remoteQueryConfig.fields,
|
||||
})
|
||||
|
||||
const [orderExchange] = await remoteQuery(queryObject, undefined, {
|
||||
const [orderExchange] = await remoteQuery(queryObject, {
|
||||
throwIfKeyNotFound: true,
|
||||
})
|
||||
|
||||
|
||||
@@ -140,7 +140,6 @@ export const refetchBatchProducts = async (
|
||||
fields: remapKeysForProduct(fields ?? []),
|
||||
})
|
||||
|
||||
// @ts-expect-error "Remote query can return null"
|
||||
created = remoteQuery(createdQuery)
|
||||
}
|
||||
|
||||
@@ -153,7 +152,6 @@ export const refetchBatchProducts = async (
|
||||
fields: remapKeysForProduct(fields ?? []),
|
||||
})
|
||||
|
||||
// @ts-expect-error "Remote query can return null"
|
||||
updated = remoteQuery(updatedQuery)
|
||||
}
|
||||
|
||||
@@ -187,7 +185,6 @@ export const refetchBatchVariants = async (
|
||||
fields: remapKeysForVariant(fields ?? []),
|
||||
})
|
||||
|
||||
// @ts-expect-error "Remote query can return null"
|
||||
created = remoteQuery(createdQuery)
|
||||
}
|
||||
|
||||
@@ -200,7 +197,6 @@ export const refetchBatchVariants = async (
|
||||
fields: remapKeysForVariant(fields ?? []),
|
||||
})
|
||||
|
||||
// @ts-expect-error "Remote query can return null"
|
||||
updated = remoteQuery(updatedQuery)
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ export const refetchBatchRules = async (
|
||||
fields: fields,
|
||||
})
|
||||
|
||||
// @ts-expect-error "Remote query can return null"
|
||||
created = remoteQuery(createdQuery)
|
||||
}
|
||||
|
||||
@@ -55,7 +54,6 @@ export const refetchBatchRules = async (
|
||||
fields: fields,
|
||||
})
|
||||
|
||||
// @ts-expect-error "Remote query can return null"
|
||||
updated = remoteQuery(updatedQuery)
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ export const GET = async (
|
||||
fields: req.remoteQueryConfig.fields,
|
||||
})
|
||||
|
||||
const [orderReturn] = await remoteQuery(queryObject, undefined, {
|
||||
const [orderReturn] = await remoteQuery(queryObject, {
|
||||
throwIfKeyNotFound: true,
|
||||
})
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ export const refetchBatchRules = async (
|
||||
fields: fields,
|
||||
})
|
||||
|
||||
// @ts-expect-error "Remote query can return null"
|
||||
created = remoteQuery(createdQuery)
|
||||
}
|
||||
|
||||
@@ -58,7 +57,6 @@ export const refetchBatchRules = async (
|
||||
fields: fields,
|
||||
})
|
||||
|
||||
// @ts-expect-error "Remote query can return null"
|
||||
updated = remoteQuery(updatedQuery)
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ export async function getVariantInventoryItems({
|
||||
"inventory.*",
|
||||
"inventory.location_levels.*",
|
||||
],
|
||||
})
|
||||
} as any)
|
||||
|
||||
const links = await remoteQuery(linkQuery)
|
||||
|
||||
|
||||
@@ -4,13 +4,14 @@ import {
|
||||
isString,
|
||||
remoteQueryObjectFromString,
|
||||
} from "@medusajs/utils"
|
||||
import { MedusaRequest } from "../../types/routing"
|
||||
|
||||
export const refetchEntities = async (
|
||||
entryPoint: string,
|
||||
idOrFilter: string | object,
|
||||
scope: MedusaContainer,
|
||||
fields: string[],
|
||||
pagination: object = {}
|
||||
pagination: MedusaRequest["remoteQueryConfig"]["pagination"] = {}
|
||||
) => {
|
||||
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
const filters = isString(idOrFilter) ? { id: idOrFilter } : idOrFilter
|
||||
|
||||
@@ -13,7 +13,7 @@ const defaultConfig = {
|
||||
borderStyle: `double`,
|
||||
} as boxen.Options
|
||||
|
||||
export default async function ({ port, directory }) {
|
||||
export default async function ({ types, directory }) {
|
||||
const args = process.argv
|
||||
|
||||
const argv =
|
||||
@@ -25,6 +25,10 @@ export default async function ({ port, directory }) {
|
||||
args.shift()
|
||||
args.shift()
|
||||
|
||||
if (types) {
|
||||
args.push("--types")
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-constructing the path to Medusa CLI to execute the
|
||||
* start command.
|
||||
@@ -95,6 +99,7 @@ export default async function ({ port, directory }) {
|
||||
"static",
|
||||
"private",
|
||||
"src/admin/**/*",
|
||||
".medusa/**/*",
|
||||
],
|
||||
})
|
||||
|
||||
|
||||
@@ -2,25 +2,35 @@ import express from "express"
|
||||
import { track } from "medusa-telemetry"
|
||||
import { scheduleJob } from "node-schedule"
|
||||
|
||||
import { logger } from "@medusajs/framework"
|
||||
import { gqlSchemaToTypes, logger } from "@medusajs/framework"
|
||||
import { GracefulShutdownServer } from "@medusajs/utils"
|
||||
import loaders from "../loaders"
|
||||
import path from "path"
|
||||
|
||||
const EVERY_SIXTH_HOUR = "0 */6 * * *"
|
||||
const CRON_SCHEDULE = EVERY_SIXTH_HOUR
|
||||
|
||||
export default async function ({ port, directory }) {
|
||||
export default async function ({ port, directory, types }) {
|
||||
async function start() {
|
||||
track("CLI_START")
|
||||
|
||||
const app = express()
|
||||
|
||||
try {
|
||||
const { shutdown } = await loaders({
|
||||
const { shutdown, gqlSchema } = await loaders({
|
||||
directory,
|
||||
expressApp: app,
|
||||
})
|
||||
|
||||
if (gqlSchema && types) {
|
||||
const outputDirGeneratedTypes = path.join(directory, ".medusa")
|
||||
await gqlSchemaToTypes({
|
||||
outputDir: outputDirGeneratedTypes,
|
||||
schema: gqlSchema,
|
||||
})
|
||||
logger.info("Geneated modules types")
|
||||
}
|
||||
|
||||
const serverActivity = logger.activity(`Creating server`)
|
||||
const server = GracefulShutdownServer.create(
|
||||
app.listen(port).on("listening", () => {
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
container,
|
||||
expressLoader,
|
||||
featureFlagsLoader,
|
||||
GraphQLSchema,
|
||||
JobLoader,
|
||||
LinkLoader,
|
||||
logger,
|
||||
@@ -133,6 +134,7 @@ export default async ({
|
||||
container: MedusaContainer
|
||||
app: Express
|
||||
shutdown: () => Promise<void>
|
||||
gqlSchema?: GraphQLSchema
|
||||
}> => {
|
||||
const container = await initializeContainer(rootDirectory)
|
||||
const configModule = container.resolve(
|
||||
@@ -149,6 +151,7 @@ export default async ({
|
||||
onApplicationStart,
|
||||
onApplicationShutdown,
|
||||
onApplicationPrepareShutdown,
|
||||
gqlSchema,
|
||||
} = await new MedusaAppLoader().load()
|
||||
|
||||
const workflowsSourcePaths = plugins.map((p) => join(p.resolve, "workflows"))
|
||||
@@ -184,5 +187,6 @@ export default async ({
|
||||
container,
|
||||
app: expressApp,
|
||||
shutdown,
|
||||
gqlSchema,
|
||||
}
|
||||
}
|
||||
+10
-2
@@ -1,12 +1,12 @@
|
||||
import { IApiKeyModuleService } from "@medusajs/types"
|
||||
import { ApiKeyType, Module, Modules } from "@medusajs/utils"
|
||||
import { ApiKeyModuleService } from "@services"
|
||||
import crypto from "crypto"
|
||||
import { moduleIntegrationTestRunner } from "medusa-test-utils"
|
||||
import {
|
||||
createPublishableKeyFixture,
|
||||
createSecretKeyFixture,
|
||||
} from "../__fixtures__"
|
||||
import { ApiKeyModuleService } from "@services"
|
||||
|
||||
jest.setTimeout(100000)
|
||||
|
||||
@@ -47,7 +47,9 @@ moduleIntegrationTestRunner<IApiKeyModuleService>({
|
||||
|
||||
expect(Object.keys(linkable)).toEqual(["apiKey"])
|
||||
|
||||
linkable.apiKey.toJSON = undefined
|
||||
Object.keys(linkable).forEach((key) => {
|
||||
delete linkable[key].toJSON
|
||||
})
|
||||
|
||||
expect(linkable.apiKey).toEqual({
|
||||
id: {
|
||||
@@ -56,6 +58,12 @@ moduleIntegrationTestRunner<IApiKeyModuleService>({
|
||||
serviceName: "apiKey",
|
||||
field: "apiKey",
|
||||
},
|
||||
publishable_key_id: {
|
||||
field: "apiKey",
|
||||
linkable: "publishable_key_id",
|
||||
primaryKey: "publishable_key_id",
|
||||
serviceName: "apiKey",
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.API_KEY, {
|
||||
linkableKeys: {
|
||||
// Merged with the autogenerated ones to maintain backward compatibility
|
||||
publishable_key_id: "ApiKey",
|
||||
},
|
||||
})
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
FindConfig,
|
||||
IApiKeyModuleService,
|
||||
InternalModuleDeclaration,
|
||||
ModuleJoinerConfig,
|
||||
ModulesSdkTypes,
|
||||
} from "@medusajs/types"
|
||||
import { ApiKey } from "@models"
|
||||
@@ -28,6 +29,7 @@ import {
|
||||
MedusaService,
|
||||
promiseAll,
|
||||
} from "@medusajs/utils"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
|
||||
const scrypt = util.promisify(crypto.scrypt)
|
||||
|
||||
@@ -55,6 +57,10 @@ export class ApiKeyModuleService
|
||||
this.apiKeyService_ = apiKeyService
|
||||
}
|
||||
|
||||
__joinerConfig(): ModuleJoinerConfig {
|
||||
return joinerConfig
|
||||
}
|
||||
|
||||
//@ts-expect-error
|
||||
createApiKeys(
|
||||
data: ApiKeyTypes.CreateApiKeyDTO[],
|
||||
|
||||
+81
-9
@@ -3,9 +3,9 @@ import { FulfillmentSetDTO, IFulfillmentModuleService } from "@medusajs/types"
|
||||
import { Module, Modules } from "@medusajs/utils"
|
||||
import { FulfillmentModuleService, FulfillmentProviderService } from "@services"
|
||||
import {
|
||||
SuiteOptions,
|
||||
initModules,
|
||||
moduleIntegrationTestRunner,
|
||||
SuiteOptions,
|
||||
} from "medusa-test-utils"
|
||||
import { resolve } from "path"
|
||||
import { createFullDataStructure } from "../../__fixtures__"
|
||||
@@ -109,10 +109,18 @@ moduleIntegrationTestRunner({
|
||||
}).linkable
|
||||
|
||||
expect(Object.keys(linkable)).toEqual([
|
||||
"fulfillment",
|
||||
"fulfillmentAddress",
|
||||
"fulfillmentItem",
|
||||
"fulfillmentLabel",
|
||||
"fulfillmentProvider",
|
||||
"fulfillmentSet",
|
||||
"shippingOption",
|
||||
"fulfillment",
|
||||
"geoZone",
|
||||
"serviceZone",
|
||||
"shippingOptionRule",
|
||||
"shippingOptionType",
|
||||
"shippingOption",
|
||||
"shippingProfile",
|
||||
])
|
||||
|
||||
Object.keys(linkable).forEach((key) => {
|
||||
@@ -120,12 +128,36 @@ moduleIntegrationTestRunner({
|
||||
})
|
||||
|
||||
expect(linkable).toEqual({
|
||||
fulfillment: {
|
||||
fulfillmentAddress: {
|
||||
id: {
|
||||
linkable: "fulfillment_id",
|
||||
linkable: "fulfillment_address_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "fulfillment",
|
||||
field: "fulfillment",
|
||||
field: "fulfillmentAddress",
|
||||
},
|
||||
},
|
||||
fulfillmentItem: {
|
||||
id: {
|
||||
linkable: "fulfillment_item_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "fulfillment",
|
||||
field: "fulfillmentItem",
|
||||
},
|
||||
},
|
||||
fulfillmentLabel: {
|
||||
id: {
|
||||
linkable: "fulfillment_label_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "fulfillment",
|
||||
field: "fulfillmentLabel",
|
||||
},
|
||||
},
|
||||
fulfillmentProvider: {
|
||||
id: {
|
||||
linkable: "fulfillment_provider_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "fulfillment",
|
||||
field: "fulfillmentProvider",
|
||||
},
|
||||
},
|
||||
fulfillmentSet: {
|
||||
@@ -136,12 +168,28 @@ moduleIntegrationTestRunner({
|
||||
field: "fulfillmentSet",
|
||||
},
|
||||
},
|
||||
shippingOption: {
|
||||
fulfillment: {
|
||||
id: {
|
||||
linkable: "shipping_option_id",
|
||||
linkable: "fulfillment_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "fulfillment",
|
||||
field: "shippingOption",
|
||||
field: "fulfillment",
|
||||
},
|
||||
},
|
||||
geoZone: {
|
||||
id: {
|
||||
linkable: "geo_zone_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "fulfillment",
|
||||
field: "geoZone",
|
||||
},
|
||||
},
|
||||
serviceZone: {
|
||||
id: {
|
||||
linkable: "service_zone_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "fulfillment",
|
||||
field: "serviceZone",
|
||||
},
|
||||
},
|
||||
shippingOptionRule: {
|
||||
@@ -152,6 +200,30 @@ moduleIntegrationTestRunner({
|
||||
field: "shippingOptionRule",
|
||||
},
|
||||
},
|
||||
shippingOptionType: {
|
||||
id: {
|
||||
linkable: "shipping_option_type_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "fulfillment",
|
||||
field: "shippingOptionType",
|
||||
},
|
||||
},
|
||||
shippingOption: {
|
||||
id: {
|
||||
linkable: "shipping_option_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "fulfillment",
|
||||
field: "shippingOption",
|
||||
},
|
||||
},
|
||||
shippingProfile: {
|
||||
id: {
|
||||
linkable: "shipping_profile_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "fulfillment",
|
||||
field: "shippingProfile",
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
import {
|
||||
Fulfillment,
|
||||
FulfillmentProvider,
|
||||
FulfillmentSet,
|
||||
ShippingOption,
|
||||
ShippingOptionRule,
|
||||
} from "@models"
|
||||
import { default as schema } from "./schema"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.FULFILLMENT, {
|
||||
schema,
|
||||
linkableKeys: {
|
||||
fulfillment_id: Fulfillment.name,
|
||||
fulfillment_set_id: FulfillmentSet.name,
|
||||
shipping_option_id: ShippingOption.name,
|
||||
shipping_option_rule_id: ShippingOptionRule.name,
|
||||
fulfillment_provider_id: FulfillmentProvider.name,
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,167 @@
|
||||
export default `
|
||||
enum GeoZoneType {
|
||||
country
|
||||
province
|
||||
city
|
||||
zip
|
||||
}
|
||||
|
||||
enum ShippingOptionPriceType {
|
||||
calculated
|
||||
flat
|
||||
}
|
||||
|
||||
type FulfillmentItem {
|
||||
id: ID!
|
||||
title: String!
|
||||
quantity: Int!
|
||||
sku: String!
|
||||
barcode: String!
|
||||
line_item_id: String
|
||||
inventory_item_id: String
|
||||
fulfillment_id: String!
|
||||
fulfillment: Fulfillment!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type FulfillmentLabel {
|
||||
id: ID!
|
||||
tracking_number: String!
|
||||
tracking_url: String!
|
||||
label_url: String!
|
||||
fulfillment_id: String!
|
||||
fulfillment: Fulfillment!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type FulfillmentProvider {
|
||||
id: ID!
|
||||
name: String!
|
||||
metadata: JSON
|
||||
shipping_options: [ShippingOption!]!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type FulfillmentSet {
|
||||
id: ID!
|
||||
name: String!
|
||||
type: String!
|
||||
metadata: JSON
|
||||
service_zones: [ServiceZone!]!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type Fulfillment {
|
||||
id: ID!
|
||||
location_id: String!
|
||||
packed_at: DateTime
|
||||
shipped_at: DateTime
|
||||
delivered_at: DateTime
|
||||
canceled_at: DateTime
|
||||
marked_shipped_by: String
|
||||
created_by: String
|
||||
data: JSON
|
||||
provider_id: String!
|
||||
shipping_option_id: String
|
||||
metadata: JSON
|
||||
shipping_option: ShippingOption
|
||||
provider: FulfillmentProvider!
|
||||
delivery_address: FulfillmentAddress!
|
||||
items: [FulfillmentItem!]!
|
||||
labels: [FulfillmentLabel!]!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type GeoZone {
|
||||
id: ID!
|
||||
type: GeoZoneType!
|
||||
country_code: String!
|
||||
province_code: String
|
||||
city: String
|
||||
postal_expression: JSON
|
||||
metadata: JSON
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type ServiceZone {
|
||||
id: ID!
|
||||
name: String!
|
||||
metadata: JSON
|
||||
fulfillment_set: FulfillmentSet!
|
||||
fulfillment_set_id: String!
|
||||
geo_zones: [GeoZone!]!
|
||||
shipping_options: [ShippingOption!]!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type ShippingOptionRule {
|
||||
id: ID!
|
||||
attribute: String!
|
||||
operator: String!
|
||||
value: JSON
|
||||
shipping_option_id: String!
|
||||
shipping_option: ShippingOption!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type ShippingOptionType {
|
||||
id: ID!
|
||||
label: String!
|
||||
description: String!
|
||||
code: String!
|
||||
shipping_option_id: String!
|
||||
shipping_option: ShippingOption!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type ShippingOption {
|
||||
id: ID!
|
||||
name: String!
|
||||
price_type: ShippingOptionPriceType!
|
||||
service_zone_id: String!
|
||||
shipping_profile_id: String!
|
||||
provider_id: String!
|
||||
shipping_option_type_id: String
|
||||
data: JSON
|
||||
metadata: JSON
|
||||
service_zone: ServiceZone!
|
||||
shipping_profile: ShippingProfile!
|
||||
fulfillment_provider: FulfillmentProvider!
|
||||
type: ShippingOptionType!
|
||||
rules: [ShippingOptionRule!]!
|
||||
fulfillments: [Fulfillment!]!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type ShippingProfile {
|
||||
id: ID!
|
||||
name: String!
|
||||
type: String!
|
||||
metadata: JSON
|
||||
shipping_options: [ShippingOption!]!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
`
|
||||
@@ -1,6 +1,11 @@
|
||||
import { MedusaModule } from "@medusajs/modules-sdk"
|
||||
import { ModuleJoinerConfig, ModuleJoinerRelationship } from "@medusajs/types"
|
||||
import { camelToSnakeCase, lowerCaseFirst, toPascalCase } from "@medusajs/utils"
|
||||
import {
|
||||
camelToSnakeCase,
|
||||
isString,
|
||||
lowerCaseFirst,
|
||||
toPascalCase,
|
||||
} from "@medusajs/utils"
|
||||
import { composeTableName } from "./compose-link-name"
|
||||
|
||||
export function generateGraphQLSchema(
|
||||
@@ -38,15 +43,18 @@ export function generateGraphQLSchema(
|
||||
)
|
||||
}
|
||||
|
||||
const extJoinerConfig = MedusaModule.getJoinerConfig(
|
||||
/* const extJoinerConfig = MedusaModule.getJoinerConfig(
|
||||
extend.relationship.serviceName
|
||||
)
|
||||
let extendedEntityName =
|
||||
extJoinerConfig?.linkableKeys?.[extend.relationship.foreignKey]!
|
||||
)*/
|
||||
|
||||
if (!isReadOnlyLink && !extendedEntityName && (!primary || !foreign)) {
|
||||
const extendedEntityName =
|
||||
extendedModule[extend.serviceName].__joinerConfig.linkableKeys[
|
||||
extend.relationship.primaryKey
|
||||
]
|
||||
|
||||
if (!isReadOnlyLink && (!primary || !foreign || !extendedEntityName)) {
|
||||
logger.warn(
|
||||
`Link modules schema: No linkable key found for ${extend.relationship.foreignKey} on module ${extend.relationship.serviceName}.`
|
||||
`Link modules schema: No linkable key found for ${extend.relationship.primaryKey} on module ${extend.serviceName}.`
|
||||
)
|
||||
|
||||
continue
|
||||
@@ -57,15 +65,82 @@ export function generateGraphQLSchema(
|
||||
)
|
||||
|
||||
let type = extend.relationship.isList ? `[${entityName}]` : entityName
|
||||
if (extJoinerConfig?.isReadOnlyLink) {
|
||||
type = extend.relationship.isList
|
||||
if (joinerConfig?.isReadOnlyLink) {
|
||||
// TODO: In readonly, the relation ship of the extend should be applied on all entities in the module that have the relationshiop foregin key attribute
|
||||
/*type = extend.relationship.isList
|
||||
? `[${extendedEntityName}]`
|
||||
: extendedEntityName
|
||||
: extendedEntityName*/
|
||||
continue
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the field aliases shortcut to extend the entity with it
|
||||
*/
|
||||
const fieldsAliasesField = Object.entries(extend.fieldAlias || {})
|
||||
.map(([field, config]) => {
|
||||
const path = isString(config) ? config : config.path
|
||||
const isList = isString(config)
|
||||
? extend.relationship.isList
|
||||
: config.isList ?? extend.relationship.isList
|
||||
|
||||
const pathSegments = path.split(",").reverse()
|
||||
|
||||
/*const relationshipMarkerIndex = pathSegments.findIndex((segment) => {
|
||||
return !!joinerConfig.relationships!.find(
|
||||
(relation) => relation.alias === targetEntityAlias
|
||||
)
|
||||
})
|
||||
|
||||
if (relationshipMarkerIndex === -1) {
|
||||
return
|
||||
}*/
|
||||
|
||||
/*const relationshipPropertyPath = pathSegments
|
||||
.slice(0, relationshipMarkerIndex + 1)
|
||||
.reverse()*/
|
||||
|
||||
const targetEntityAlias = path.split(".").pop()
|
||||
|
||||
const targetEntityRelation = joinerConfig.relationships?.find(
|
||||
(relation) => relation.alias === targetEntityAlias
|
||||
)
|
||||
|
||||
if (!targetEntityRelation) {
|
||||
return
|
||||
}
|
||||
|
||||
const targetEntityName = MedusaModule.getJoinerConfig(
|
||||
targetEntityRelation.serviceName
|
||||
).linkableKeys?.[targetEntityRelation.foreignKey]
|
||||
|
||||
if (!targetEntityName) {
|
||||
logger.warn(
|
||||
`Link modules schema: No linkable key found for ${targetEntityRelation.foreignKey} on module ${targetEntityRelation.serviceName}.`
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: Re visit field aliases that access properties from a type
|
||||
/*const targetEntityType = `${targetEntityName}${
|
||||
relationshipPropertyPath.length
|
||||
? relationshipPropertyPath.reduce((acc, value) => {
|
||||
return `${acc}[${value}]`
|
||||
}, targetEntityName)
|
||||
: ""
|
||||
}`*/
|
||||
|
||||
return `${field}: ${
|
||||
isList ? `[${targetEntityName}]` : targetEntityName
|
||||
}`
|
||||
})
|
||||
.filter(Boolean)
|
||||
|
||||
typeDef += `
|
||||
extend type ${extend.serviceName} {
|
||||
extend type ${extendedEntityName} {
|
||||
${fieldName}: ${type}
|
||||
|
||||
${fieldsAliasesField.join("\n")}
|
||||
}
|
||||
`
|
||||
}
|
||||
@@ -92,14 +167,26 @@ export function generateGraphQLSchema(
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: temporary, every module might always expose their schema
|
||||
const doesPrimaryExportSchema = !!MedusaModule.getJoinerConfig(
|
||||
primary.serviceName
|
||||
)?.schema
|
||||
const doesForeignExportSchema = !!MedusaModule.getJoinerConfig(
|
||||
foreign.serviceName
|
||||
)?.schema
|
||||
|
||||
// Link table relationships
|
||||
const primaryField = `${camelToSnakeCase(primary.alias)}: ${toPascalCase(
|
||||
const primaryField = doesPrimaryExportSchema
|
||||
? `${camelToSnakeCase(primary.alias)}: ${toPascalCase(
|
||||
composeTableName(primary.serviceName)
|
||||
)}`
|
||||
: ""
|
||||
|
||||
const foreignField = `${camelToSnakeCase(foreign.alias)}: ${toPascalCase(
|
||||
const foreignField = doesForeignExportSchema
|
||||
? `${camelToSnakeCase(foreign.alias)}: ${toPascalCase(
|
||||
composeTableName(foreign.serviceName)
|
||||
)}`
|
||||
: ""
|
||||
|
||||
typeDef += `
|
||||
type ${entityName} {
|
||||
|
||||
@@ -15,26 +15,14 @@ moduleIntegrationTestRunner<IOrderModuleService>({
|
||||
expect(Object.keys(linkable)).toEqual([
|
||||
"order",
|
||||
"orderAddress",
|
||||
"orderLineItem",
|
||||
"orderLineItemAdjustment",
|
||||
"orderLineItemTaxLine",
|
||||
"orderShippingMethod",
|
||||
"orderShippingMethodAdjustment",
|
||||
"orderShippingMethodTaxLine",
|
||||
"orderTransaction",
|
||||
"orderChange",
|
||||
"orderChangeAction",
|
||||
"orderItem",
|
||||
"orderSummary",
|
||||
"orderShipping",
|
||||
"returnReason",
|
||||
"return",
|
||||
"returnItem",
|
||||
"orderClaim",
|
||||
"orderClaimItem",
|
||||
"orderClaimItemImage",
|
||||
"orderExchange",
|
||||
"orderExchangeItem",
|
||||
"orderLineItem",
|
||||
"orderShippingMethod",
|
||||
"orderTransaction",
|
||||
"return",
|
||||
"returnReason",
|
||||
])
|
||||
|
||||
Object.keys(linkable).forEach((key) => {
|
||||
@@ -58,6 +46,42 @@ moduleIntegrationTestRunner<IOrderModuleService>({
|
||||
field: "orderAddress",
|
||||
},
|
||||
},
|
||||
orderChange: {
|
||||
id: {
|
||||
linkable: "order_change_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderChange",
|
||||
},
|
||||
},
|
||||
orderClaim: {
|
||||
id: {
|
||||
linkable: "order_claim_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderClaim",
|
||||
},
|
||||
claim_id: {
|
||||
linkable: "claim_id",
|
||||
primaryKey: "claim_id",
|
||||
serviceName: "order",
|
||||
field: "orderClaim",
|
||||
},
|
||||
},
|
||||
orderExchange: {
|
||||
id: {
|
||||
linkable: "order_exchange_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderExchange",
|
||||
},
|
||||
exchange_id: {
|
||||
linkable: "exchange_id",
|
||||
primaryKey: "exchange_id",
|
||||
serviceName: "order",
|
||||
field: "orderExchange",
|
||||
},
|
||||
},
|
||||
orderLineItem: {
|
||||
id: {
|
||||
linkable: "order_line_item_id",
|
||||
@@ -66,22 +90,6 @@ moduleIntegrationTestRunner<IOrderModuleService>({
|
||||
field: "orderLineItem",
|
||||
},
|
||||
},
|
||||
orderLineItemAdjustment: {
|
||||
id: {
|
||||
linkable: "order_line_item_adjustment_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderLineItemAdjustment",
|
||||
},
|
||||
},
|
||||
orderLineItemTaxLine: {
|
||||
id: {
|
||||
linkable: "order_line_item_tax_line_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderLineItemTaxLine",
|
||||
},
|
||||
},
|
||||
orderShippingMethod: {
|
||||
id: {
|
||||
linkable: "order_shipping_method_id",
|
||||
@@ -90,22 +98,6 @@ moduleIntegrationTestRunner<IOrderModuleService>({
|
||||
field: "orderShippingMethod",
|
||||
},
|
||||
},
|
||||
orderShippingMethodAdjustment: {
|
||||
id: {
|
||||
linkable: "order_shipping_method_adjustment_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderShippingMethodAdjustment",
|
||||
},
|
||||
},
|
||||
orderShippingMethodTaxLine: {
|
||||
id: {
|
||||
linkable: "order_shipping_method_tax_line_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderShippingMethodTaxLine",
|
||||
},
|
||||
},
|
||||
orderTransaction: {
|
||||
id: {
|
||||
linkable: "order_transaction_id",
|
||||
@@ -114,54 +106,6 @@ moduleIntegrationTestRunner<IOrderModuleService>({
|
||||
field: "orderTransaction",
|
||||
},
|
||||
},
|
||||
orderChange: {
|
||||
id: {
|
||||
linkable: "order_change_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderChange",
|
||||
},
|
||||
},
|
||||
orderChangeAction: {
|
||||
id: {
|
||||
linkable: "order_change_action_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderChangeAction",
|
||||
},
|
||||
},
|
||||
orderItem: {
|
||||
id: {
|
||||
linkable: "order_item_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderItem",
|
||||
},
|
||||
},
|
||||
orderSummary: {
|
||||
id: {
|
||||
linkable: "order_summary_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderSummary",
|
||||
},
|
||||
},
|
||||
orderShipping: {
|
||||
id: {
|
||||
linkable: "order_shipping_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderShipping",
|
||||
},
|
||||
},
|
||||
returnReason: {
|
||||
id: {
|
||||
linkable: "return_reason_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "returnReason",
|
||||
},
|
||||
},
|
||||
return: {
|
||||
id: {
|
||||
linkable: "return_id",
|
||||
@@ -170,52 +114,12 @@ moduleIntegrationTestRunner<IOrderModuleService>({
|
||||
field: "return",
|
||||
},
|
||||
},
|
||||
returnItem: {
|
||||
returnReason: {
|
||||
id: {
|
||||
linkable: "return_item_id",
|
||||
linkable: "return_reason_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "returnItem",
|
||||
},
|
||||
},
|
||||
orderClaim: {
|
||||
id: {
|
||||
linkable: "order_claim_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderClaim",
|
||||
},
|
||||
},
|
||||
orderClaimItem: {
|
||||
id: {
|
||||
linkable: "order_claim_item_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderClaimItem",
|
||||
},
|
||||
},
|
||||
orderClaimItemImage: {
|
||||
id: {
|
||||
linkable: "order_claim_item_image_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderClaimItemImage",
|
||||
},
|
||||
},
|
||||
orderExchange: {
|
||||
id: {
|
||||
linkable: "order_exchange_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderExchange",
|
||||
},
|
||||
},
|
||||
orderExchangeItem: {
|
||||
id: {
|
||||
linkable: "order_exchange_item_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "order",
|
||||
field: "orderExchangeItem",
|
||||
field: "returnReason",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { OrderModuleService } from "@services"
|
||||
import { Module, Modules } from "@medusajs/utils"
|
||||
import { OrderModuleService } from "@services"
|
||||
|
||||
export default Module(Modules.ORDER, {
|
||||
service: OrderModuleService,
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
import {
|
||||
Order,
|
||||
OrderAddress,
|
||||
OrderChange,
|
||||
OrderClaim,
|
||||
OrderExchange,
|
||||
OrderLineItem,
|
||||
OrderShippingMethod,
|
||||
OrderTransaction,
|
||||
Return,
|
||||
ReturnReason,
|
||||
} from "@models"
|
||||
import { default as schema } from "./schema"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.ORDER, {
|
||||
schema,
|
||||
linkableKeys: {
|
||||
claim_id: "OrderClaim",
|
||||
exchange_id: "OrderExchange",
|
||||
},
|
||||
models: [
|
||||
Order,
|
||||
OrderAddress,
|
||||
OrderChange,
|
||||
OrderClaim,
|
||||
OrderExchange,
|
||||
OrderLineItem,
|
||||
OrderShippingMethod,
|
||||
OrderTransaction,
|
||||
Return,
|
||||
ReturnReason,
|
||||
],
|
||||
})
|
||||
@@ -0,0 +1,573 @@
|
||||
export default `
|
||||
enum ChangeActionType {
|
||||
CANCEL_RETURN_ITEM
|
||||
FULFILL_ITEM
|
||||
CANCEL_ITEM_FULFILLMENT
|
||||
ITEM_ADD
|
||||
ITEM_REMOVE
|
||||
ITEM_UPDATE
|
||||
RECEIVE_DAMAGED_RETURN_ITEM
|
||||
RECEIVE_RETURN_ITEM
|
||||
RETURN_ITEM
|
||||
SHIPPING_ADD
|
||||
SHIPPING_REMOVE
|
||||
SHIP_ITEM
|
||||
WRITE_OFF_ITEM
|
||||
REINSTATE_ITEM
|
||||
}
|
||||
|
||||
type OrderSummary {
|
||||
total: Float
|
||||
subtotal: Float
|
||||
total_tax: Float
|
||||
ordered_total: Float
|
||||
fulfilled_total: Float
|
||||
returned_total: Float
|
||||
return_request_total: Float
|
||||
write_off_total: Float
|
||||
projected_total: Float
|
||||
net_total: Float
|
||||
net_subtotal: Float
|
||||
net_total_tax: Float
|
||||
balance: Float
|
||||
paid_total: Float
|
||||
refunded_total: Float
|
||||
pending_difference: Float
|
||||
raw_pending_difference: JSON
|
||||
}
|
||||
|
||||
type OrderAdjustmentLine {
|
||||
id: ID!
|
||||
code: String
|
||||
amount: Float
|
||||
order_id: String!
|
||||
description: String
|
||||
promotion_id: String
|
||||
provider_id: String
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
}
|
||||
|
||||
type OrderShippingMethodAdjustment {
|
||||
id: ID!
|
||||
code: String
|
||||
amount: Float
|
||||
order_id: String!
|
||||
description: String
|
||||
promotion_id: String
|
||||
provider_id: String
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
shipping_method: OrderShippingMethod
|
||||
shipping_method_id: String!
|
||||
}
|
||||
|
||||
type OrderLineItemAdjustment {
|
||||
id: ID!
|
||||
code: String
|
||||
amount: Float
|
||||
order_id: String!
|
||||
description: String
|
||||
promotion_id: String
|
||||
provider_id: String
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
item: OrderLineItem
|
||||
item_id: String!
|
||||
}
|
||||
|
||||
type OrderTaxLine {
|
||||
id: ID!
|
||||
description: String
|
||||
tax_rate_id: String
|
||||
code: String!
|
||||
rate: Float
|
||||
provider_id: String
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
}
|
||||
|
||||
type OrderShippingMethodTaxLine {
|
||||
id: ID!
|
||||
description: String
|
||||
tax_rate_id: String
|
||||
code: String!
|
||||
rate: Float
|
||||
provider_id: String
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
shipping_method: OrderShippingMethod
|
||||
shipping_method_id: String!
|
||||
total: Float
|
||||
subtotal: Float
|
||||
raw_total: JSON
|
||||
raw_subtotal: JSON
|
||||
}
|
||||
|
||||
type OrderLineItemTaxLine {
|
||||
id: ID!
|
||||
description: String
|
||||
tax_rate_id: String
|
||||
code: String!
|
||||
rate: Float
|
||||
provider_id: String
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
item: OrderLineItem
|
||||
item_id: String!
|
||||
total: Float
|
||||
subtotal: Float
|
||||
raw_total: JSON
|
||||
raw_subtotal: JSON
|
||||
}
|
||||
|
||||
type OrderAddress {
|
||||
id: ID!
|
||||
customer_id: String
|
||||
first_name: String
|
||||
last_name: String
|
||||
phone: String
|
||||
company: String
|
||||
address_1: String
|
||||
address_2: String
|
||||
city: String
|
||||
country_code: String
|
||||
province: String
|
||||
postal_code: String
|
||||
metadata: JSON
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
}
|
||||
|
||||
type OrderShippingMethod {
|
||||
id: ID!
|
||||
order_id: String!
|
||||
name: String!
|
||||
description: String
|
||||
amount: Float
|
||||
raw_amount: JSON
|
||||
is_tax_inclusive: Boolean
|
||||
shipping_option_id: String
|
||||
data: JSON
|
||||
metadata: JSON
|
||||
tax_lines: [OrderShippingMethodTaxLine]
|
||||
adjustments: [OrderShippingMethodAdjustment]
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
original_total: Float
|
||||
original_subtotal: Float
|
||||
original_tax_total: Float
|
||||
total: Float
|
||||
subtotal: Float
|
||||
tax_total: Float
|
||||
discount_total: Float
|
||||
discount_tax_total: Float
|
||||
raw_original_total: JSON
|
||||
raw_original_subtotal: JSON
|
||||
raw_original_tax_total: JSON
|
||||
raw_total: JSON
|
||||
raw_subtotal: JSON
|
||||
raw_tax_total: JSON
|
||||
raw_discount_total: JSON
|
||||
raw_discount_tax_total: JSON
|
||||
}
|
||||
|
||||
type OrderLineItem {
|
||||
id: ID!
|
||||
title: String!
|
||||
subtitle: String
|
||||
thumbnail: String
|
||||
variant_id: String
|
||||
product_id: String
|
||||
product_title: String
|
||||
product_description: String
|
||||
product_subtitle: String
|
||||
product_type: String
|
||||
product_collection: String
|
||||
product_handle: String
|
||||
variant_sku: String
|
||||
variant_barcode: String
|
||||
variant_title: String
|
||||
variant_option_values: JSON
|
||||
requires_shipping: Boolean!
|
||||
is_discountable: Boolean!
|
||||
is_tax_inclusive: Boolean!
|
||||
compare_at_unit_price: Float
|
||||
raw_compare_at_unit_price: JSON
|
||||
unit_price: Float!
|
||||
raw_unit_price: JSON
|
||||
quantity: Int!
|
||||
raw_quantity: JSON
|
||||
tax_lines: [OrderLineItemTaxLine]
|
||||
adjustments: [OrderLineItemAdjustment]
|
||||
detail: OrderItem!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
metadata: JSON
|
||||
original_total: Float
|
||||
original_subtotal: Float
|
||||
original_tax_total: Float
|
||||
item_total: Float
|
||||
item_subtotal: Float
|
||||
item_tax_total: Float
|
||||
total: Float
|
||||
subtotal: Float
|
||||
tax_total: Float
|
||||
discount_total: Float
|
||||
discount_tax_total: Float
|
||||
refundable_total: Float
|
||||
refundable_total_per_unit: Float
|
||||
raw_original_total: JSON
|
||||
raw_original_subtotal: JSON
|
||||
raw_original_tax_total: JSON
|
||||
raw_item_total: JSON
|
||||
raw_item_subtotal: JSON
|
||||
raw_item_tax_total: JSON
|
||||
raw_total: JSON
|
||||
raw_subtotal: JSON
|
||||
raw_tax_total: JSON
|
||||
raw_discount_total: JSON
|
||||
raw_discount_tax_total: JSON
|
||||
raw_refundable_total: JSON
|
||||
raw_refundable_total_per_unit: JSON
|
||||
}
|
||||
|
||||
type OrderItem {
|
||||
id: ID!
|
||||
item_id: String!
|
||||
item: OrderLineItem!
|
||||
quantity: Int!
|
||||
raw_quantity: JSON
|
||||
fulfilled_quantity: Int!
|
||||
raw_fulfilled_quantity: JSON
|
||||
shipped_quantity: Int!
|
||||
raw_shipped_quantity: JSON
|
||||
return_requested_quantity: Int!
|
||||
raw_return_requested_quantity: JSON
|
||||
return_received_quantity: Int!
|
||||
raw_return_received_quantity: JSON
|
||||
return_dismissed_quantity: Int!
|
||||
raw_return_dismissed_quantity: JSON
|
||||
written_off_quantity: Int!
|
||||
raw_written_off_quantity: JSON
|
||||
metadata: JSON
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
}
|
||||
|
||||
enum OrderStatus {
|
||||
pending
|
||||
completed
|
||||
draft
|
||||
archived
|
||||
canceled
|
||||
requires_action
|
||||
}
|
||||
|
||||
type Order {
|
||||
id: ID!
|
||||
version: Int!
|
||||
order_change: OrderChange
|
||||
status: OrderStatus!
|
||||
region_id: String
|
||||
customer_id: String
|
||||
sales_channel_id: String
|
||||
email: String
|
||||
currency_code: String!
|
||||
shipping_address: OrderAddress
|
||||
billing_address: OrderAddress
|
||||
items: [OrderLineItem]
|
||||
shipping_methods: [OrderShippingMethod]
|
||||
transactions: [OrderTransaction]
|
||||
summary: OrderSummary
|
||||
metadata: JSON
|
||||
canceled_at: DateTime
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
original_item_total: Float!
|
||||
original_item_subtotal: Float!
|
||||
original_item_tax_total: Float!
|
||||
item_total: Float!
|
||||
item_subtotal: Float!
|
||||
item_tax_total: Float!
|
||||
original_total: Float!
|
||||
original_subtotal: Float!
|
||||
original_tax_total: Float!
|
||||
total: Float!
|
||||
subtotal: Float!
|
||||
tax_total: Float!
|
||||
discount_total: Float!
|
||||
discount_tax_total: Float!
|
||||
gift_card_total: Float!
|
||||
gift_card_tax_total: Float!
|
||||
shipping_total: Float!
|
||||
shipping_subtotal: Float!
|
||||
shipping_tax_total: Float!
|
||||
original_shipping_total: Float!
|
||||
original_shipping_subtotal: Float!
|
||||
original_shipping_tax_total: Float!
|
||||
raw_original_item_total: JSON
|
||||
raw_original_item_subtotal: JSON
|
||||
raw_original_item_tax_total: JSON
|
||||
raw_item_total: JSON
|
||||
raw_item_subtotal: JSON
|
||||
raw_item_tax_total: JSON
|
||||
raw_original_total: JSON
|
||||
raw_original_subtotal: JSON
|
||||
raw_original_tax_total: JSON
|
||||
raw_total: JSON
|
||||
raw_subtotal: JSON
|
||||
raw_tax_total: JSON
|
||||
raw_discount_total: JSON
|
||||
raw_discount_tax_total: JSON
|
||||
raw_gift_card_total: JSON
|
||||
raw_gift_card_tax_total: JSON
|
||||
raw_shipping_total: JSON
|
||||
raw_shipping_subtotal: JSON
|
||||
raw_shipping_tax_total: JSON
|
||||
raw_original_shipping_total: JSON
|
||||
raw_original_shipping_subtotal: JSON
|
||||
raw_original_shipping_tax_total: JSON
|
||||
}
|
||||
|
||||
enum ReturnStatus {
|
||||
requested
|
||||
received
|
||||
partially_received
|
||||
canceled
|
||||
}
|
||||
|
||||
type Return {
|
||||
id: ID!
|
||||
status: ReturnStatus!
|
||||
refund_amount: Float
|
||||
order_id: String!
|
||||
items: [OrderReturnItem]!
|
||||
}
|
||||
|
||||
type OrderReturnItem {
|
||||
id: ID!
|
||||
return_id: String!
|
||||
order_id: String!
|
||||
item_id: String!
|
||||
reason_id: String
|
||||
quantity: Int!
|
||||
raw_quantity: JSON
|
||||
received_quantity: Int
|
||||
raw_received_quantity: JSON
|
||||
metadata: JSON
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
}
|
||||
|
||||
type OrderClaimItem {
|
||||
id: ID!
|
||||
claim_id: String!
|
||||
order_id: String!
|
||||
item_id: String!
|
||||
quantity: Int!
|
||||
reason: ClaimReason!
|
||||
raw_quantity: JSON
|
||||
metadata: JSON
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
}
|
||||
|
||||
type OrderClaimItemImage {
|
||||
id: ID!
|
||||
claim_item_id: String!
|
||||
url: String
|
||||
metadata: JSON
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
}
|
||||
|
||||
type OrderExchangeItem {
|
||||
id: ID!
|
||||
exchange_id: String!
|
||||
order_id: String!
|
||||
item_id: String!
|
||||
quantity: Int!
|
||||
raw_quantity: JSON
|
||||
metadata: JSON
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
}
|
||||
|
||||
type OrderClaim {
|
||||
order_id: String!
|
||||
claim_items: [OrderClaimItem]!
|
||||
additional_items: [OrderClaimItem]!
|
||||
return: Return
|
||||
return_id: String
|
||||
no_notification: Boolean
|
||||
refund_amount: Float
|
||||
created_by: String
|
||||
}
|
||||
|
||||
type OrderExchange {
|
||||
order_id: String!
|
||||
return_items: [OrderReturnItem]!
|
||||
additional_items: [OrderClaimItem]!
|
||||
no_notification: Boolean
|
||||
difference_due: Float
|
||||
return: Return
|
||||
return_id: String
|
||||
created_by: String
|
||||
}
|
||||
|
||||
enum PaymentStatus {
|
||||
not_paid
|
||||
awaiting
|
||||
authorized
|
||||
partially_authorized
|
||||
captured
|
||||
partially_captured
|
||||
partially_refunded
|
||||
refunded
|
||||
canceled
|
||||
requires_action
|
||||
}
|
||||
|
||||
enum FulfillmentStatus {
|
||||
not_fulfilled
|
||||
partially_fulfilled
|
||||
fulfilled
|
||||
partially_shipped
|
||||
shipped
|
||||
partially_delivered
|
||||
delivered
|
||||
canceled
|
||||
}
|
||||
|
||||
type OrderDetail {
|
||||
id: ID!
|
||||
version: Int!
|
||||
order_change: OrderChange
|
||||
status: OrderStatus!
|
||||
region_id: String
|
||||
customer_id: String
|
||||
sales_channel_id: String
|
||||
email: String
|
||||
currency_code: String!
|
||||
shipping_address: OrderAddress
|
||||
billing_address: OrderAddress
|
||||
items: [OrderLineItem]
|
||||
shipping_methods: [OrderShippingMethod]
|
||||
transactions: [OrderTransaction]
|
||||
summary: OrderSummary
|
||||
metadata: JSON
|
||||
canceled_at: DateTime
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
original_item_total: Float!
|
||||
original_item_subtotal: Float!
|
||||
original_item_tax_total: Float!
|
||||
item_total: Float!
|
||||
item_subtotal: Float!
|
||||
item_tax_total: Float!
|
||||
original_total: Float!
|
||||
original_subtotal: Float!
|
||||
original_tax_total: Float!
|
||||
total: Float!
|
||||
subtotal: Float!
|
||||
tax_total: Float!
|
||||
discount_total: Float!
|
||||
discount_tax_total: Float!
|
||||
gift_card_total: Float!
|
||||
gift_card_tax_total: Float!
|
||||
shipping_total: Float!
|
||||
shipping_subtotal: Float!
|
||||
shipping_tax_total: Float!
|
||||
original_shipping_total: Float!
|
||||
original_shipping_subtotal: Float!
|
||||
original_shipping_tax_total: Float!
|
||||
raw_original_item_total: JSON
|
||||
raw_original_item_subtotal: JSON
|
||||
raw_original_item_tax_total: JSON
|
||||
raw_item_total: JSON
|
||||
raw_item_subtotal: JSON
|
||||
raw_item_tax_total: JSON
|
||||
raw_original_total: JSON
|
||||
raw_original_subtotal: JSON
|
||||
raw_original_tax_total: JSON
|
||||
raw_total: JSON
|
||||
raw_subtotal: JSON
|
||||
raw_tax_total: JSON
|
||||
raw_discount_total: JSON
|
||||
raw_discount_tax_total: JSON
|
||||
raw_gift_card_total: JSON
|
||||
raw_gift_card_tax_total: JSON
|
||||
raw_shipping_total: JSON
|
||||
raw_shipping_subtotal: JSON
|
||||
raw_shipping_tax_total: JSON
|
||||
raw_original_shipping_total: JSON
|
||||
raw_original_shipping_subtotal: JSON
|
||||
raw_original_shipping_tax_total: JSON
|
||||
payment_collections: [PaymentCollection]
|
||||
payment_status: PaymentStatus!
|
||||
fulfillments: [Fulfillment]
|
||||
fulfillment_status: FulfillmentStatus!
|
||||
}
|
||||
|
||||
type OrderChange {
|
||||
id: ID!
|
||||
version: Int!
|
||||
change_type: String
|
||||
order_id: String!
|
||||
return_id: String
|
||||
exchange_id: String
|
||||
claim_id: String
|
||||
order: Order!
|
||||
return_order: Return
|
||||
exchange: OrderExchange
|
||||
claim: OrderClaim
|
||||
actions: [OrderChangeAction]!
|
||||
status: String!
|
||||
requested_by: String
|
||||
requested_at: DateTime
|
||||
confirmed_by: String
|
||||
confirmed_at: DateTime
|
||||
declined_by: String
|
||||
declined_reason: String
|
||||
metadata: JSON
|
||||
declined_at: DateTime
|
||||
canceled_by: String
|
||||
canceled_at: DateTime
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
}
|
||||
|
||||
type OrderChangeAction {
|
||||
id: ID!
|
||||
order_change_id: String
|
||||
order_change: OrderChange
|
||||
order_id: String
|
||||
return_id: String
|
||||
claim_id: String
|
||||
exchange_id: String
|
||||
order: Order
|
||||
reference: String!
|
||||
reference_id: String!
|
||||
action: ChangeActionType!
|
||||
details: JSON
|
||||
internal_note: String
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
}
|
||||
|
||||
type OrderTransaction {
|
||||
id: ID!
|
||||
order_id: String!
|
||||
order: Order!
|
||||
amount: Float!
|
||||
raw_amount: JSON
|
||||
currency_code: String!
|
||||
reference: String!
|
||||
reference_id: String!
|
||||
metadata: JSON
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
}
|
||||
|
||||
`
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
FindConfig,
|
||||
IOrderModuleService,
|
||||
InternalModuleDeclaration,
|
||||
ModuleJoinerConfig,
|
||||
ModulesSdkTypes,
|
||||
OrderDTO,
|
||||
OrderReturnReasonDTO,
|
||||
@@ -73,6 +74,7 @@ import {
|
||||
UpdateOrderShippingMethodTaxLineDTO,
|
||||
} from "@types"
|
||||
import { UpdateReturnReasonDTO } from "src/types/return-reason"
|
||||
import { joinerConfig } from "../joiner-config"
|
||||
import {
|
||||
ApplyOrderChangeDTO,
|
||||
applyChangesToOrder,
|
||||
@@ -260,6 +262,10 @@ export default class OrderModuleService<
|
||||
this.orderExchangeService_ = orderExchangeService
|
||||
}
|
||||
|
||||
__joinerConfig(): ModuleJoinerConfig {
|
||||
return joinerConfig
|
||||
}
|
||||
|
||||
private shouldIncludeTotals(config: FindConfig<any>): boolean {
|
||||
const totalFields = [
|
||||
"total",
|
||||
|
||||
+10
-1
@@ -4,8 +4,8 @@ import { PaymentModuleService } from "@services"
|
||||
import { moduleIntegrationTestRunner } from "medusa-test-utils"
|
||||
import {
|
||||
createPaymentCollections,
|
||||
createPayments,
|
||||
createPaymentSessions,
|
||||
createPayments,
|
||||
} from "../../../__fixtures__"
|
||||
|
||||
jest.setTimeout(30000)
|
||||
@@ -23,6 +23,7 @@ moduleIntegrationTestRunner<IPaymentModuleService>({
|
||||
"payment",
|
||||
"paymentCollection",
|
||||
"paymentProvider",
|
||||
"paymentSession",
|
||||
"refundReason",
|
||||
])
|
||||
|
||||
@@ -55,6 +56,14 @@ moduleIntegrationTestRunner<IPaymentModuleService>({
|
||||
field: "paymentProvider",
|
||||
},
|
||||
},
|
||||
paymentSession: {
|
||||
id: {
|
||||
field: "paymentSession",
|
||||
linkable: "payment_session_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "payment",
|
||||
},
|
||||
},
|
||||
refundReason: {
|
||||
id: {
|
||||
linkable: "refund_reason_id",
|
||||
|
||||
@@ -6,8 +6,10 @@ import {
|
||||
PaymentSession,
|
||||
RefundReason,
|
||||
} from "@models"
|
||||
import { default as schema } from "./schema"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.PAYMENT, {
|
||||
schema,
|
||||
models: [
|
||||
Payment,
|
||||
PaymentCollection,
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
export default `
|
||||
enum PaymentCollectionStatus {
|
||||
not_paid
|
||||
awaiting
|
||||
authorized
|
||||
partially_authorized
|
||||
canceled
|
||||
}
|
||||
|
||||
enum PaymentSessionStatus {
|
||||
authorized
|
||||
captured
|
||||
pending
|
||||
requires_more
|
||||
error
|
||||
canceled
|
||||
}
|
||||
|
||||
type PaymentCollection {
|
||||
id: ID!
|
||||
currency_code: String!
|
||||
region_id: String!
|
||||
amount: Float!
|
||||
authorized_amount: Float
|
||||
refunded_amount: Float
|
||||
captured_amount: Float
|
||||
completed_at: DateTime
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
metadata: JSON
|
||||
status: PaymentCollectionStatus!
|
||||
payment_providers: [PaymentProviderDTO!]!
|
||||
payment_sessions: [PaymentSessionDTO]
|
||||
payments: [PaymentDTO]
|
||||
}
|
||||
|
||||
type Payment {
|
||||
id: ID!
|
||||
amount: Float!
|
||||
raw_amount: Float
|
||||
authorized_amount: Float
|
||||
raw_authorized_amount: Float
|
||||
currency_code: String!
|
||||
provider_id: String!
|
||||
cart_id: String
|
||||
order_id: String
|
||||
order_edit_id: String
|
||||
customer_id: String
|
||||
data: JSON
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
captured_at: DateTime
|
||||
canceled_at: DateTime
|
||||
captured_amount: Float
|
||||
raw_captured_amount: Float
|
||||
refunded_amount: Float
|
||||
raw_refunded_amount: Float
|
||||
captures: [CaptureDTO]
|
||||
refunds: [RefundDTO]
|
||||
payment_collection_id: String!
|
||||
payment_collection: PaymentCollectionDTO
|
||||
payment_session: PaymentSessionDTO
|
||||
}
|
||||
|
||||
type Capture {
|
||||
id: ID!
|
||||
amount: Float!
|
||||
created_at: DateTime!
|
||||
created_by: String
|
||||
payment: Payment!
|
||||
}
|
||||
|
||||
type Refund {
|
||||
id: ID!
|
||||
amount: Float!
|
||||
refund_reason_id: String
|
||||
refund_reason: RefundReason
|
||||
note: String
|
||||
created_at: DateTime!
|
||||
created_by: String
|
||||
payment: Payment!
|
||||
}
|
||||
|
||||
type PaymentSession {
|
||||
id: ID!
|
||||
amount: Float!
|
||||
currency_code: String!
|
||||
provider_id: String!
|
||||
data: JSON!
|
||||
context: JSON
|
||||
status: PaymentSessionStatus!
|
||||
authorized_at: DateTime
|
||||
payment_collection_id: String!
|
||||
payment_collection: PaymentCollection
|
||||
payment: Payment
|
||||
}
|
||||
|
||||
type PaymentProvider {
|
||||
id: ID!
|
||||
is_enabled: String!
|
||||
}
|
||||
|
||||
type RefundReason {
|
||||
id: ID!
|
||||
label: String!
|
||||
description: String
|
||||
metadata: JSON
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
}
|
||||
`
|
||||
@@ -1,6 +1,8 @@
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
import { Price, PriceList, PricePreference, PriceSet } from "@models"
|
||||
import { default as schema } from "./schema"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.PRICING, {
|
||||
schema,
|
||||
models: [PriceSet, PriceList, Price, PricePreference],
|
||||
})
|
||||
@@ -1,15 +1,58 @@
|
||||
export const schema = `
|
||||
type PriceSet {
|
||||
id: String!
|
||||
money_amounts: [MoneyAmount]
|
||||
id: ID!
|
||||
prices: [MoneyAmount]
|
||||
calculated_price: CalculatedPriceSet
|
||||
}
|
||||
|
||||
type MoneyAmount {
|
||||
id: String!
|
||||
id: ID!
|
||||
currency_code: String
|
||||
amount: Float
|
||||
min_quantity: Float
|
||||
max_quantity: Float
|
||||
rules_count: Int
|
||||
price_rules: [PriceRule]
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type PriceRule {
|
||||
id: ID!
|
||||
price_set_id: String!
|
||||
price_set: PriceSet
|
||||
attribute: String!
|
||||
value: String!
|
||||
priority: Int!
|
||||
price_id: String!
|
||||
price_list_id: String!
|
||||
created_at: DateTime
|
||||
updated_at: DateTime
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type CalculatedPriceSet {
|
||||
id: ID!
|
||||
is_calculated_price_price_list: Boolean
|
||||
is_calculated_price_tax_inclusive: Boolean
|
||||
calculated_amount: Float
|
||||
raw_calculated_amount: JSON
|
||||
is_original_price_price_list: Boolean
|
||||
is_original_price_tax_inclusive: Boolean
|
||||
original_amount: Float
|
||||
raw_original_amount: JSON
|
||||
currency_code: String
|
||||
calculated_price: PriceDetails
|
||||
original_price: PriceDetails
|
||||
}
|
||||
|
||||
type PriceDetails {
|
||||
id: ID
|
||||
price_list_id: String
|
||||
price_list_type: String
|
||||
min_quantity: Float
|
||||
max_quantity: Float
|
||||
}
|
||||
`
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
} from "../__fixtures__/product"
|
||||
|
||||
import { IProductModuleService, ProductDTO } from "@medusajs/types"
|
||||
import { kebabCase, Module, Modules, ProductStatus } from "@medusajs/utils"
|
||||
import { Module, Modules, ProductStatus, kebabCase } from "@medusajs/utils"
|
||||
import { SqlEntityManager } from "@mikro-orm/postgresql"
|
||||
import {
|
||||
ProductCategoryService,
|
||||
@@ -77,6 +77,12 @@ moduleIntegrationTestRunner<Service>({
|
||||
serviceName: "productService",
|
||||
field: "productVariant",
|
||||
},
|
||||
variant_id: {
|
||||
field: "productVariant",
|
||||
linkable: "variant_id",
|
||||
primaryKey: "variant_id",
|
||||
serviceName: "productService",
|
||||
},
|
||||
},
|
||||
productOption: {
|
||||
id: {
|
||||
|
||||
@@ -9,8 +9,10 @@ import {
|
||||
ProductVariant,
|
||||
} from "@models"
|
||||
import ProductImage from "./models/product-image"
|
||||
import { default as schema } from "./schema"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.PRODUCT, {
|
||||
schema,
|
||||
models: [
|
||||
Product,
|
||||
ProductVariant,
|
||||
@@ -21,6 +23,10 @@ export const joinerConfig = defineJoinerConfig(Modules.PRODUCT, {
|
||||
ProductCollection,
|
||||
ProductCategory,
|
||||
],
|
||||
linkableKeys: {
|
||||
// Merged with the autogenerated ones to maintain backward compatibility
|
||||
variant_id: "ProductVariant",
|
||||
},
|
||||
primaryKeys: ["id", "handle"],
|
||||
alias: [
|
||||
{
|
||||
|
||||
@@ -0,0 +1,148 @@
|
||||
export default `
|
||||
enum ProductStatus {
|
||||
draft
|
||||
proposed
|
||||
published
|
||||
rejected
|
||||
}
|
||||
|
||||
type Product {
|
||||
id: ID!
|
||||
title: String!
|
||||
handle: String!
|
||||
subtitle: String
|
||||
description: String
|
||||
is_giftcard: Boolean!
|
||||
status: ProductStatus!
|
||||
thumbnail: String
|
||||
width: Float
|
||||
weight: Float
|
||||
length: Float
|
||||
height: Float
|
||||
origin_country: String
|
||||
hs_code: String
|
||||
mid_code: String
|
||||
material: String
|
||||
collection: ProductCollection
|
||||
collection_id: String
|
||||
categories: [ProductCategory]
|
||||
type: ProductType
|
||||
type_id: String
|
||||
tags: [ProductTag!]!
|
||||
variants: [ProductVariant!]!
|
||||
options: [ProductOption!]!
|
||||
images: [ProductImage!]!
|
||||
discountable: Boolean
|
||||
external_id: String
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
metadata: JSON
|
||||
}
|
||||
|
||||
type ProductVariant {
|
||||
id: ID!
|
||||
title: String!
|
||||
sku: String
|
||||
barcode: String
|
||||
ean: String
|
||||
upc: String
|
||||
allow_backorder: Boolean!
|
||||
manage_inventory: Boolean!
|
||||
requires_shipping: Boolean!
|
||||
hs_code: String
|
||||
origin_country: String
|
||||
mid_code: String
|
||||
material: String
|
||||
weight: Float
|
||||
length: Float
|
||||
height: Float
|
||||
width: Float
|
||||
options: [ProductOptionValue!]!
|
||||
metadata: JSON
|
||||
product: Product
|
||||
product_id: String
|
||||
variant_rank: Int
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type ProductCategory {
|
||||
id: ID!
|
||||
name: String!
|
||||
description: String!
|
||||
handle: String!
|
||||
is_active: Boolean!
|
||||
is_internal: Boolean!
|
||||
rank: Int!
|
||||
metadata: JSON
|
||||
parent_category: ProductCategory
|
||||
parent_category_id: String
|
||||
category_children: [ProductCategory!]!
|
||||
products: [Product!]!
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type ProductTag {
|
||||
id: ID!
|
||||
value: String!
|
||||
metadata: JSON
|
||||
products: [Product]
|
||||
}
|
||||
|
||||
type ProductCollection {
|
||||
id: ID!
|
||||
title: String!
|
||||
handle: String!
|
||||
metadata: JSON
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
products: [Product]
|
||||
}
|
||||
|
||||
type ProductType {
|
||||
id: ID!
|
||||
value: String!
|
||||
metadata: JSON
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type ProductOption {
|
||||
id: ID!
|
||||
title: String!
|
||||
product: Product
|
||||
product_id: String
|
||||
values: [ProductOptionValue!]!
|
||||
metadata: JSON
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type ProductImage {
|
||||
id: ID!
|
||||
url: String!
|
||||
metadata: JSON
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type ProductOptionValue {
|
||||
id: ID!
|
||||
value: String!
|
||||
option: ProductOption
|
||||
option_id: String
|
||||
metadata: JSON
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
`
|
||||
@@ -1,6 +1,8 @@
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
import { Campaign, Promotion, PromotionRule } from "@models"
|
||||
import { default as schema } from "./schema"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.PROMOTION, {
|
||||
schema,
|
||||
models: [Promotion, Campaign, PromotionRule],
|
||||
})
|
||||
@@ -0,0 +1,96 @@
|
||||
export default `
|
||||
enum PromotionTypeValues {
|
||||
standard
|
||||
buyget
|
||||
}
|
||||
|
||||
enum PromotionRuleOperatorValues {
|
||||
gt
|
||||
lt
|
||||
eq
|
||||
ne
|
||||
in
|
||||
lte
|
||||
gte
|
||||
}
|
||||
|
||||
enum CampaignBudgetTypeValues {
|
||||
spend
|
||||
usage
|
||||
}
|
||||
|
||||
enum ApplicationMethodTypeValues {
|
||||
fixed
|
||||
percentage
|
||||
}
|
||||
|
||||
enum ApplicationMethodTargetTypeValues {
|
||||
order
|
||||
shipping_methods
|
||||
items
|
||||
}
|
||||
|
||||
enum ApplicationMethodAllocationValues {
|
||||
each
|
||||
across
|
||||
}
|
||||
|
||||
type Promotion {
|
||||
id: ID!
|
||||
code: String
|
||||
type: PromotionTypeValues
|
||||
is_automatic: Boolean
|
||||
application_method: ApplicationMethod
|
||||
rules: [PromotionRule]
|
||||
campaign_id: String
|
||||
campaign: Campaign
|
||||
}
|
||||
|
||||
type PromotionRule {
|
||||
id: ID!
|
||||
description: String
|
||||
attribute: String
|
||||
operator: PromotionRuleOperatorValues
|
||||
values: [PromotionRuleValue!]!
|
||||
}
|
||||
|
||||
type PromotionRuleValue {
|
||||
id: ID!
|
||||
value: String
|
||||
}
|
||||
|
||||
type Campaign {
|
||||
id: ID!
|
||||
name: String
|
||||
description: String
|
||||
campaign_identifier: String
|
||||
starts_at: DateTime
|
||||
ends_at: DateTime
|
||||
budget: CampaignBudget
|
||||
promotions: [Promotion]
|
||||
}
|
||||
|
||||
type CampaignBudget {
|
||||
id: ID!
|
||||
type: CampaignBudgetTypeValues
|
||||
limit: Int
|
||||
used: Int
|
||||
currency_code: String
|
||||
}
|
||||
|
||||
type ApplicationMethod {
|
||||
id: ID!
|
||||
type: ApplicationMethodTypeValues
|
||||
target_type: ApplicationMethodTargetTypeValues
|
||||
allocation: ApplicationMethodAllocationValues
|
||||
value: Float
|
||||
currency_code: String
|
||||
max_quantity: Int
|
||||
buy_rules_min_quantity: Int
|
||||
apply_to_quantity: Int
|
||||
promotion: Promotion
|
||||
target_rules: [PromotionRule]
|
||||
buy_rules: [PromotionRule]
|
||||
}
|
||||
|
||||
`
|
||||
@@ -0,0 +1,6 @@
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
import { default as schema } from "./schema"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.SALES_CHANNEL, {
|
||||
schema,
|
||||
})
|
||||
@@ -0,0 +1,12 @@
|
||||
export default `
|
||||
type SalesChannel {
|
||||
id: ID!
|
||||
name: String!
|
||||
description: String
|
||||
is_disabled: Boolean!
|
||||
created_at: DateTime!
|
||||
metadata: JSON
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
`
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
FilterableSalesChannelProps,
|
||||
InternalModuleDeclaration,
|
||||
ISalesChannelModuleService,
|
||||
ModuleJoinerConfig,
|
||||
ModulesSdkTypes,
|
||||
SalesChannelDTO,
|
||||
UpdateSalesChannelDTO,
|
||||
@@ -21,6 +22,7 @@ import {
|
||||
|
||||
import { SalesChannel } from "@models"
|
||||
import { UpdateSalesChanneInput } from "@types"
|
||||
import { joinerConfig } from "../joinfer-config"
|
||||
|
||||
type InjectedDependencies = {
|
||||
baseRepository: DAL.RepositoryService
|
||||
@@ -46,6 +48,10 @@ export default class SalesChannelModuleService
|
||||
this.salesChannelService_ = salesChannelService
|
||||
}
|
||||
|
||||
__joinerConfig(): ModuleJoinerConfig {
|
||||
return joinerConfig
|
||||
}
|
||||
|
||||
// @ts-expect-error
|
||||
async createSalesChannels(
|
||||
data: CreateSalesChannelDTO[],
|
||||
|
||||
+18
-1
@@ -15,14 +15,31 @@ moduleIntegrationTestRunner<IStockLocationService>({
|
||||
service: StockLocationModuleService,
|
||||
}).linkable
|
||||
|
||||
expect(Object.keys(linkable)).toEqual(["stockLocation"])
|
||||
expect(Object.keys(linkable)).toEqual([
|
||||
"stockLocationAddress",
|
||||
"stockLocation",
|
||||
])
|
||||
|
||||
Object.keys(linkable).forEach((key) => {
|
||||
delete linkable[key].toJSON
|
||||
})
|
||||
|
||||
expect(linkable).toEqual({
|
||||
stockLocationAddress: {
|
||||
id: {
|
||||
linkable: "stock_location_address_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "stockLocationService",
|
||||
field: "stockLocationAddress",
|
||||
},
|
||||
},
|
||||
stockLocation: {
|
||||
id: {
|
||||
field: "stockLocation",
|
||||
linkable: "stock_location_id",
|
||||
primaryKey: "id",
|
||||
serviceName: "stockLocationService",
|
||||
},
|
||||
location_id: {
|
||||
linkable: "location_id",
|
||||
primaryKey: "location_id",
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { defineJoinerConfig, Modules } from "@medusajs/utils"
|
||||
import { StockLocation } from "./models"
|
||||
import { default as schema } from "./schema"
|
||||
|
||||
export const joinerConfig = defineJoinerConfig(Modules.STOCK_LOCATION, {
|
||||
schema,
|
||||
linkableKeys: {
|
||||
stock_location_id: StockLocation.name,
|
||||
location_id: StockLocation.name,
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
export default `
|
||||
type StockLocationAddress {
|
||||
id: ID
|
||||
address_1: String!
|
||||
address_2: String
|
||||
company: String
|
||||
country_code: String!
|
||||
city: String
|
||||
phone: String
|
||||
postal_code: String
|
||||
province: String
|
||||
metadata: JSON
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
type StockLocation {
|
||||
id: ID!
|
||||
name: String!
|
||||
metadata: JSON
|
||||
address_id: ID!
|
||||
address: StockLocationAddress
|
||||
created_at: DateTime!
|
||||
updated_at: DateTime!
|
||||
deleted_at: DateTime
|
||||
}
|
||||
|
||||
`
|
||||
Reference in new issue
Block a user