diff --git a/packages/cli/create-medusa-app/package.json b/packages/cli/create-medusa-app/package.json index b92d4ace64f7f..91cee99b2d57c 100644 --- a/packages/cli/create-medusa-app/package.json +++ b/packages/cli/create-medusa-app/package.json @@ -13,7 +13,6 @@ "watch": "tsc --watch" }, "dependencies": { - "@medusajs/utils": "^1.11.9", "boxen": "^5", "chalk": "^5.2.0", "commander": "^10.0.1", diff --git a/packages/cli/create-medusa-app/src/commands/create.ts b/packages/cli/create-medusa-app/src/commands/create.ts index 5b76df3cb6965..248ac4f4a1114 100644 --- a/packages/cli/create-medusa-app/src/commands/create.ts +++ b/packages/cli/create-medusa-app/src/commands/create.ts @@ -25,7 +25,7 @@ import { installNextjsStarter, startNextjsStarter, } from "../utils/nextjs-utils.js" -import { getNodeVersion, MIN_SUPPORTED_NODE_VERSION } from "@medusajs/utils" +import { getNodeVersion, MIN_SUPPORTED_NODE_VERSION } from "../utils/node-version.js" const slugify = slugifyType.default diff --git a/packages/cli/create-medusa-app/src/utils/node-version.ts b/packages/cli/create-medusa-app/src/utils/node-version.ts new file mode 100644 index 0000000000000..fa09891d5b411 --- /dev/null +++ b/packages/cli/create-medusa-app/src/utils/node-version.ts @@ -0,0 +1,7 @@ +export function getNodeVersion(): number { + const [major] = process.versions.node.split('.').map(Number) + + return major +} + +export const MIN_SUPPORTED_NODE_VERSION = 20 \ No newline at end of file diff --git a/packages/core/js-sdk/src/index.ts b/packages/core/js-sdk/src/index.ts index 9ad987dadb4a8..0cb79bd52827d 100644 --- a/packages/core/js-sdk/src/index.ts +++ b/packages/core/js-sdk/src/index.ts @@ -21,4 +21,18 @@ class Medusa { } export default Medusa -export { FetchError } from "./client" + +export { FetchError, Client } from "./client" +export { Admin } from "./admin" +export { Auth } from "./auth" +export { Store } from "./store" +export { + Config, + ClientHeaders, + ClientFetch, + FetchArgs, + FetchInput, + FetchStreamResponse, + Logger, + ServerSentEventMessage, +} from "./types" diff --git a/packages/core/orchestration/src/transaction/orchestrator-builder.ts b/packages/core/orchestration/src/transaction/orchestrator-builder.ts index 227107caa7ab5..3bdbe5d981f36 100644 --- a/packages/core/orchestration/src/transaction/orchestrator-builder.ts +++ b/packages/core/orchestration/src/transaction/orchestrator-builder.ts @@ -22,9 +22,11 @@ export class OrchestratorBuilder { this.steps = { depth: -1, parent: null, - next: steps + next: Object.keys(steps ?? {}).length ? JSON.parse( - JSON.stringify((steps.action ? steps : steps.next) as InternalStep) + JSON.stringify( + (steps!.action ? steps : steps!.next) as InternalStep + ) ) : undefined, } diff --git a/packages/core/orchestration/src/transaction/transaction-orchestrator.ts b/packages/core/orchestration/src/transaction/transaction-orchestrator.ts index 2cf277c77850d..b5e1f3b3338fd 100644 --- a/packages/core/orchestration/src/transaction/transaction-orchestrator.ts +++ b/packages/core/orchestration/src/transaction/transaction-orchestrator.ts @@ -549,6 +549,16 @@ export class TransactionOrchestrator extends EventEmitter { step.changeState(TransactionStepState.TIMEOUT) + if (error?.stack) { + const workflowId = transaction.modelId + const stepAction = step.definition.action + const sourcePath = transaction.getFlow().metadata?.sourcePath + const sourceStack = sourcePath + ? `\n⮑ \sat ${sourcePath}: [${workflowId} -> ${stepAction} (${TransactionHandlerType.INVOKE})]` + : `\n⮑ \sat [${workflowId} -> ${stepAction} (${TransactionHandlerType.INVOKE})]` + error.stack += sourceStack + } + transaction.addError( step.definition.action!, TransactionHandlerType.INVOKE, @@ -602,13 +612,21 @@ export class TransactionOrchestrator extends EventEmitter { step.changeStatus(TransactionStepStatus.PERMANENT_FAILURE) if (!isTimeout) { - transaction.addError( - step.definition.action!, - step.isCompensating() - ? TransactionHandlerType.COMPENSATE - : TransactionHandlerType.INVOKE, - error - ) + const handlerType = step.isCompensating() + ? TransactionHandlerType.COMPENSATE + : TransactionHandlerType.INVOKE + + if (error?.stack) { + const workflowId = transaction.modelId + const stepAction = step.definition.action + const sourcePath = transaction.getFlow().metadata?.sourcePath + const sourceStack = sourcePath + ? `\n⮑ \sat ${sourcePath}: [${workflowId} -> ${stepAction} (${TransactionHandlerType.INVOKE})]` + : `\n⮑ \sat [${workflowId} -> ${stepAction} (${TransactionHandlerType.INVOKE})]` + error.stack += sourceStack + } + + transaction.addError(step.definition.action!, handlerType, error) } if (!step.isCompensating()) { diff --git a/packages/core/orchestration/src/transaction/types.ts b/packages/core/orchestration/src/transaction/types.ts index ef486528584f2..b83ebab1bf484 100644 --- a/packages/core/orchestration/src/transaction/types.ts +++ b/packages/core/orchestration/src/transaction/types.ts @@ -243,6 +243,7 @@ export type TransactionFlow = { metadata?: { eventGroupId?: string parentIdempotencyKey?: string + sourcePath?: string [key: string]: unknown } hasAsyncSteps: boolean diff --git a/packages/core/types/src/fulfillment/provider.ts b/packages/core/types/src/fulfillment/provider.ts index 122383bb67f83..df16bb158a049 100644 --- a/packages/core/types/src/fulfillment/provider.ts +++ b/packages/core/types/src/fulfillment/provider.ts @@ -1,18 +1,29 @@ +export type FulfillmentOption = { + /** + * The option's ID. + * + * @example express + */ + id: string + /** + * Whether the option can be used to return items. + */ + is_return?: boolean + [k: string]: unknown +} + export interface IFulfillmentProvider { /** - * @ignore * * Return a unique identifier to retrieve the fulfillment plugin provider */ getIdentifier(): string /** - * @ignore * * Return the available fulfillment options for the given data. */ - getFulfillmentOptions(): Promise[]> + getFulfillmentOptions(): Promise /** - * @ignore * * Validate the given fulfillment data. */ @@ -22,19 +33,16 @@ export interface IFulfillmentProvider { context: Record ): Promise /** - * @ignore * * Validate the given option. */ validateOption(data: Record): Promise /** - * @ignore * * Check if the provider can calculate the fulfillment price. */ canCalculate(data: Record): Promise /** - * @ignore * * Calculate the price for the given fulfillment option. */ @@ -44,7 +52,6 @@ export interface IFulfillmentProvider { context: Record ): Promise /** - * @ignore * * Create a fulfillment for the given data. */ @@ -55,25 +62,21 @@ export interface IFulfillmentProvider { fulfillment: Record ): Promise> /** - * @ignore * * Cancel the given fulfillment. */ cancelFulfillment(fulfillment: Record): Promise /** - * @ignore * * Get the documents for the given fulfillment data. */ getFulfillmentDocuments(data: Record): Promise /** - * @ignore * * Create a return for the given data. */ createReturnFulfillment(fromData: Record): Promise /** - * @ignore * * Get the documents for the given return data. */ @@ -82,13 +85,11 @@ export interface IFulfillmentProvider { documentType: string ): Promise /** - * @ignore * * Get the documents for the given return data. */ getReturnDocuments(data: Record): Promise /** - * @ignore * * Get the documents for the given shipment data. */ diff --git a/packages/core/utils/src/fulfillment/provider.ts b/packages/core/utils/src/fulfillment/provider.ts index bf2e12b111222..89d81a12282df 100644 --- a/packages/core/utils/src/fulfillment/provider.ts +++ b/packages/core/utils/src/fulfillment/provider.ts @@ -1,70 +1,416 @@ -import { IFulfillmentProvider } from "@medusajs/types" +import { + IFulfillmentProvider, + FulfillmentOption +} from "@medusajs/types" +/** + * ### constructor + * + * The constructor allows you to access resources from the module's container using the first parameter, + * and the module's options using the second parameter. + * + * :::note + * + * A module's options are passed when you register it in the Medusa application. + * + * ::: + * + * If you're creating a client or establishing a connection with a third-party service, do it in the constructor. + * + * #### Example + * + * ```ts + * import { AbstractFulfillmentProviderService } from "@medusajs/framework/utils" + * import { Logger } from "@medusajs/framework/types" + * + * type InjectedDependencies = { + * logger: Logger + * } + * + * type Options = { + * apiKey: string + * } + * + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * protected logger_: Logger + * protected options_: Options + * // assuming you're initializing a client + * protected client + * + * constructor( + * { logger }: InjectedDependencies, + * options: Options + * ) { + * super() + * + * this.logger_ = logger + * this.options_ = options + * } + * } + * + * export default MyFulfillmentProviderService + * ``` + */ export class AbstractFulfillmentProviderService implements IFulfillmentProvider { + /** + * The `identifier` property holds a unique identifier of the fulfillment module provider. + * + * You can use the kebab-case name of the provider as its value. + * + * For example: + * + * ```ts + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * static identifier = "my-fulfillment" + * + * // ... + * } + */ static identifier: string + /** + * @ignore + */ static _isFulfillmentService = true + /** + * @ignore + */ static isFulfillmentService(obj) { return obj?.constructor?._isFulfillmentService } /** - * Override this static method in order for the loader to validate the options provided to the module provider. - * @param options + * @ignore + * + * @privateRemarks + * This method is ignored as {@link validateOption} is the one used by the Fulfillment Module. */ static validateOptions(options: Record): void | never {} + /** + * @ignore + */ getIdentifier() { return (this.constructor as any).identifier } - async getFulfillmentOptions(): Promise[]> { + /** + * This method retrieves the shipping options this fulfillment provider supports. + * + * @returns The list of fulfillment options. + * + * @example + * // other imports... + * import { FulfillmentOption } from "@medusajs/framework/types" + * + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async getFulfillmentOptions(): Promise { + * return [ + * { + * id: "express" + * }, + * { + * id: "return-express", + * is_return: true + * } + * ] + * } + * } + */ + async getFulfillmentOptions(): Promise { throw Error("getFulfillmentOptions must be overridden by the child class") } + /** + * This method validates the `data` property of a shipping method and returns it. The returned data + * is stored in the shipping method's `data` property. + * + * Your fulfillment provider can use the `data` property to store additional information useful for + * handling the fulfillment later. For example, you may store an ID from the third-party fulfillment + * system. + * + * @param optionData - The `data` property of the shipping option. + * @param data - The `data` property of the shipping method. + * @param context - Context details, such as context of the cart or customer. + * @returns the data to store in the `data` property of the shipping method. + * + * @example + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async validateFulfillmentData( + * optionData: any, + * data: any, + * context: any + * ): Promise { + * // assuming your client retrieves an ID from the + * // third-party service + * const externalId = await this.client.getId() + * + * return { + * ...data, + * externalId + * } + * } + * } + */ async validateFulfillmentData(optionData, data, context): Promise { throw Error("validateFulfillmentData must be overridden by the child class") } + /** + * This method validates the `data` property of a shipping option when it's created. + * + * The `data` property can hold useful information that's later added to the `data` attribute + * of shipping methods created from this option. + * + * @param data - The data to validate. + * @return Whether the data is valid. + * + * @example + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async validateOption(data: any): Promise { + * return data.external_id !== undefined + * } + * } + */ async validateOption(data): Promise { throw Error("validateOption must be overridden by the child class") } - async canCalculate(data) { + /** + * This method indicates whether a shippin option's price is calculated during + * checkout or is fixed. + * + * @param data - The `data` property of the shipping option. + * @returns Whether the price is calculated for the shipping option. + * + * @example + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async canCalculate(data: any): Promise { + * return data.custom_type !== "fixed" + * } + * } + */ + async canCalculate(data): Promise { throw Error("canCalculate must be overridden by the child class") } - async calculatePrice(optionData, data, cart) { + /** + * This method calculates the price of a shipping option, or a shipping method when it's created. + * + * The Medusa application uses the {@link canCalculate} method first to check whether the shipping option's price is calculated. + * If it returns `true`, Medusa uses this method to retrieve the calculated price. + * + * @param optionData - The `data` property of a shipping option. + * @param data - If the price is calculated for a shipping option, it's the `data` of the shipping option. Otherwise, it's the `data of the shipping method. + * @param cart - The cart details. + * @returns The calculated price + * + * @example + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async calculatePrice(optionData: any, data: any, cart: any): Promise { + * // assuming the client can calculate the price using + * // the third-party service + * const price = await this.client.calculate(data) + * + * return price + * } + * } + */ + async calculatePrice(optionData, data, cart): Promise { throw Error("calculatePrice must be overridden by the child class") } + /** + * This method is used when a fulfillment is created. If the method returns in the object a + * `data` property, it's stored in the fulfillment's `data` property. + * + * The `data` property is useful when handling the fulfillment later, + * as you can access information useful for your integration. + * + * You can also use this method to perform an action with the third-party fulfillment service. + * + * @param data - The `data` property of the shipping method this fulfillment is created for. + * @param items - The items in the fulfillment. + * @param order - The order this fulfillment is created for. + * @param fulfillment - The fulfillment's details. + * @returns The data to store in the fulfillment's `data` property. + * + * @example + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async createFulfillment( + * data: any, + * items: any, + * order: any, + * fulfillment: any + * ): Promise { + * // assuming the client creates a fulfillment + * // in the third-party service + * const externalData = await this.client.create( + * fulfillment, + * items + * ) + * + * return { + * data: { + * ...data, + * ...externalData + * } + * } + * } + * } + */ async createFulfillment(data, items, order, fulfillment): Promise { throw Error("createFulfillment must be overridden by the child class") } + /** + * This method is used when a fulfillment is canceled. Use it to perform operations + * with the third-party fulfillment service. + * + * @param fulfillment - The fulfillment's details. + * + * @example + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async cancelFulfillment(fulfillment: any): Promise { + * // assuming the client cancels a fulfillment + * // in the third-party service + * await this.client.cancel(fulfillment.id) + * } + * } + */ async cancelFulfillment(fulfillment): Promise { throw Error("cancelFulfillment must be overridden by the child class") } + /** + * This method retrieves the documents of a fulfillment. + * + * @param data - The `data` property of the fulfillment. + * @returns The fulfillment's documents. + * + * @example + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async getFulfillmentDocuments(data: any): Promise { + * // assuming the client retrieves documents + * // from a third-party service + * return await this.client.documents(data) + * } + * } + */ async getFulfillmentDocuments(data) { return [] } - async createReturnFulfillment(fromData): Promise { + /** + * This method is used when a fulfillment is created for a return. If the method returns in the object a + * `data` property, it's stored in the fulfillment's `data` property. + * + * The `data` property is useful when handling the fulfillment later, + * as you can access information useful for your integration. + * + * Use this method to perform actions necessary in the third-party fulfillment service. + * + * @param fulfillment - The fulfillment's details. + * @returns The data to store in the fulfillment's `data` property. + * + * @example + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async createReturnFulfillment(fulfillment: any): Promise { + * // assuming the client creates a fulfillment for a return + * // in the third-party service + * const externalData = await this.client.createReturn( + * fulfillment + * ) + * + * return { + * data: { + * ...fulfillment.data, + * ...externalData + * } + * } + * } + * } + */ + async createReturnFulfillment(fulfillment): Promise { throw Error("createReturn must be overridden by the child class") } + /** + * This method retrieves documents for a return's fulfillment. + * + * @param data - The `data` property of the fulfillment. + * @returns The fulfillment's documents. + * + * @example + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async getReturnDocuments(data: any): Promise { + * // assuming the client retrieves documents + * // from a third-party service + * return await this.client.documents(data) + * } + * } + */ async getReturnDocuments(data) { return [] } + /** + * This method retrieves the documents for a shipment. + * + * @param data - The `data` property of the shipmnet. + * @returns The shipment's documents. + * + * @example + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async getShipmentDocuments(data: any): Promise { + * // assuming the client retrieves documents + * // from a third-party service + * return await this.client.documents(data) + * } + * } + * + */ async getShipmentDocuments(data) { return [] } + /** + * This method retrieves the documents of a fulfillment of a certain type. + * + * @param fulfillmentData - The `data` property of the fulfillment. + * @param documentType - The document's type. For example, `invoice`. + * @returns The fulfillment's documents. + * + * @example + * class MyFulfillmentProviderService extends AbstractFulfillmentProviderService { + * // ... + * async retrieveDocuments( + * fulfillmentData: any, + * documentType: any + * ): Promise { + * // assuming the client retrieves documents + * // from a third-party service + * return await this.client.documents( + * fulfillmentData, + * documentType + * ) + * } + * } + */ async retrieveDocuments(fulfillmentData, documentType) { throw Error("retrieveDocuments must be overridden by the child class") } diff --git a/packages/core/workflows-sdk/src/helper/workflow-export.ts b/packages/core/workflows-sdk/src/helper/workflow-export.ts index a2ff478560b19..502b4e13be3f6 100644 --- a/packages/core/workflows-sdk/src/helper/workflow-export.ts +++ b/packages/core/workflows-sdk/src/helper/workflow-export.ts @@ -44,6 +44,7 @@ function createContextualWorkflowRunner< dataPreparation?: (data: TData) => Promise options?: { wrappedInput?: boolean + sourcePath?: string } container?: LoadedModule[] | MedusaContainer }): Omit< @@ -93,6 +94,7 @@ function createContextualWorkflowRunner< const flowMetadata = { eventGroupId, parentStepIdempotencyKey, + sourcePath: options?.sourcePath, } const args = [ @@ -334,6 +336,7 @@ export const exportWorkflow = ( dataPreparation?: (data: TData) => Promise, options?: { wrappedInput?: boolean + sourcePath?: string } ): MainExportedWorkflow => { function exportedWorkflow< diff --git a/packages/core/workflows-sdk/src/utils/composer/__tests__/compose.ts b/packages/core/workflows-sdk/src/utils/composer/__tests__/compose.ts index 45d01632f6965..b0f12c6682a7a 100644 --- a/packages/core/workflows-sdk/src/utils/composer/__tests__/compose.ts +++ b/packages/core/workflows-sdk/src/utils/composer/__tests__/compose.ts @@ -6,19 +6,19 @@ import { } from "@medusajs/orchestration" import { IEventBusModuleService } from "@medusajs/types" import { - Modules, composeMessage, createMedusaContainer, + Modules, promiseAll, } from "@medusajs/utils" import { asValue } from "awilix" import { - StepResponse, - WorkflowResponse, createStep, createWorkflow, parallelize, + StepResponse, transform, + WorkflowResponse, } from ".." import { MedusaWorkflow } from "../../../medusa-workflow" import { createHook } from "../create-hook" @@ -1903,7 +1903,7 @@ describe("Workflow composer", function () { action: "step1", handlerType: "invoke", error: expect.objectContaining({ - message: "invoke fail", + message: "invoke fail", }), }) diff --git a/packages/core/workflows-sdk/src/utils/composer/__tests__/index.spec.ts b/packages/core/workflows-sdk/src/utils/composer/__tests__/index.spec.ts index d2a5f989acae7..fda0482469091 100644 --- a/packages/core/workflows-sdk/src/utils/composer/__tests__/index.spec.ts +++ b/packages/core/workflows-sdk/src/utils/composer/__tests__/index.spec.ts @@ -134,6 +134,33 @@ describe("Workflow composer", () => { expect(res2).toEqual({ result: "default response" }) }) + it("should not return value if when condition is false", async function () { + const workflow = createWorkflow( + getNewWorkflowId(), + function (input: { ret: boolean }) { + const value = when({ input }, ({ input }) => { + return input.ret + }).then(() => { + return { hasValue: true } + }) + + return new WorkflowResponse(value) + } + ) + + const { result } = await workflow.run({ + input: { ret: false }, + }) + + expect(result).toEqual(undefined) + + const { result: res2 } = await workflow.run({ + input: { ret: true }, + }) + + expect(res2).toEqual({ hasValue: true }) + }) + it("should revert the workflow and sub workflow on failure", async function () { const step1Mock = jest.fn() const step1 = createStep( diff --git a/packages/core/workflows-sdk/src/utils/composer/create-workflow.ts b/packages/core/workflows-sdk/src/utils/composer/create-workflow.ts index 970dc6046434a..0f8ea3068f596 100644 --- a/packages/core/workflows-sdk/src/utils/composer/create-workflow.ts +++ b/packages/core/workflows-sdk/src/utils/composer/create-workflow.ts @@ -4,7 +4,11 @@ import { WorkflowManager, } from "@medusajs/orchestration" import { LoadedModule, MedusaContainer } from "@medusajs/types" -import { OrchestrationUtils, isString } from "@medusajs/utils" +import { + getCallerFilePath, + isString, + OrchestrationUtils, +} from "@medusajs/utils" import { ulid } from "ulid" import { exportWorkflow } from "../../helper" import { createStep } from "./create-step" @@ -34,7 +38,7 @@ global[OrchestrationUtils.SymbolMedusaWorkflowComposerContext] = null * @returns The created workflow. You can later execute the workflow by invoking it, then using its `run` method. * * @example - * import { + * import { * createWorkflow, * WorkflowResponse * } from "@medusajs/framework/workflows-sdk" @@ -50,7 +54,7 @@ global[OrchestrationUtils.SymbolMedusaWorkflowComposerContext] = null * } * * const myWorkflow = createWorkflow( - * "my-workflow", + * "my-workflow", * (input: WorkflowInput) => { * // Everything here will be executed and resolved later * // during the execution. Including the data access. @@ -92,6 +96,7 @@ export function createWorkflow( input: WorkflowData ) => void | WorkflowResponse ): ReturnWorkflow { + const fileSourcePath = getCallerFilePath() as string const name = isString(nameOrConfig) ? nameOrConfig : nameOrConfig.name const options = isString(nameOrConfig) ? {} : nameOrConfig @@ -153,6 +158,7 @@ export function createWorkflow( undefined, { wrappedInput: true, + sourcePath: fileSourcePath, } ) diff --git a/packages/core/workflows-sdk/src/utils/composer/when.ts b/packages/core/workflows-sdk/src/utils/composer/when.ts index ebbfe0dbe776f..fdb3f70959ebb 100644 --- a/packages/core/workflows-sdk/src/utils/composer/when.ts +++ b/packages/core/workflows-sdk/src/utils/composer/when.ts @@ -1,4 +1,7 @@ import { OrchestrationUtils } from "@medusajs/utils" +import { ulid } from "ulid" +import { createStep } from "./create-step" +import { StepResponse } from "./helpers/step-response" import { StepExecutionContext, WorkflowData } from "./type" type ConditionFunction = ( @@ -41,17 +44,26 @@ export function when(input, condition) { then: (fn) => { thenCalled = true const ret = fn() + let returnStep = ret const applyCondition = global[OrchestrationUtils.SymbolMedusaWorkflowComposerCondition].steps + if (ret?.__type !== OrchestrationUtils.SymbolWorkflowStep) { + const retStep = createStep( + "when-then-" + ulid(), + () => new StepResponse(ret) + ) + returnStep = retStep() + } + for (const step of applyCondition) { step.if(input, condition) } delete global[OrchestrationUtils.SymbolMedusaWorkflowComposerCondition] - return ret + return returnStep }, } } diff --git a/packages/modules/providers/fulfillment-manual/src/services/manual-fulfillment.ts b/packages/modules/providers/fulfillment-manual/src/services/manual-fulfillment.ts index 7fd765dee6404..5734782c92169 100644 --- a/packages/modules/providers/fulfillment-manual/src/services/manual-fulfillment.ts +++ b/packages/modules/providers/fulfillment-manual/src/services/manual-fulfillment.ts @@ -1,4 +1,5 @@ import { AbstractFulfillmentProviderService } from "@medusajs/framework/utils" +import { FulfillmentOption } from "@medusajs/types" // TODO rework type and DTO's @@ -9,7 +10,7 @@ export class ManualFulfillmentService extends AbstractFulfillmentProviderService super() } - async getFulfillmentOptions(): Promise[]> { + async getFulfillmentOptions(): Promise { return [ { id: "manual-fulfillment", diff --git a/yarn.lock b/yarn.lock index 54ec993c60a27..df31e34e60d59 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16913,7 +16913,6 @@ __metadata: version: 0.0.0-use.local resolution: "create-medusa-app@workspace:packages/cli/create-medusa-app" dependencies: - "@medusajs/utils": ^1.11.9 "@types/chalk": ^2.2.0 "@types/commander": ^2.12.2 "@types/configstore": ^6.0.0