diff --git a/.changeset/chilled-dingos-float.md b/.changeset/chilled-dingos-float.md new file mode 100644 index 0000000000..a8444e875b --- /dev/null +++ b/.changeset/chilled-dingos-float.md @@ -0,0 +1,7 @@ +--- +"@medusajs/utils": patch +"@medusajs/modules-sdk": patch +"@medusajs/types": patch +--- + +Feat/shipping method init diff --git a/.eslintignore b/.eslintignore index a2f3463632..37ab11f81e 100644 --- a/.eslintignore +++ b/.eslintignore @@ -30,6 +30,7 @@ packages/* !packages/medusa-react !packages/workflow-engine-redis !packages/workflow-engine-inmemory +!packages/fulfillment **/models/* diff --git a/.eslintrc.js b/.eslintrc.js index 56edede0b3..f083ae8b04 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -102,6 +102,7 @@ module.exports = { "./packages/types/tsconfig.json", "./packages/workflow-engine-redis/tsconfig.spec.json", "./packages/workflow-engine-inmemory/tsconfig.spec.json", + "./packages/fulfillment/tsconfig.spec.json", ], }, rules: { diff --git a/packages/fulfillment/.gitignore b/packages/fulfillment/.gitignore new file mode 100644 index 0000000000..874c6c69d3 --- /dev/null +++ b/packages/fulfillment/.gitignore @@ -0,0 +1,6 @@ +/dist +node_modules +.DS_store +.env* +.env +*.sql diff --git a/packages/fulfillment/README.md b/packages/fulfillment/README.md new file mode 100644 index 0000000000..27d9186041 --- /dev/null +++ b/packages/fulfillment/README.md @@ -0,0 +1 @@ +# Fulfillment Module diff --git a/packages/fulfillment/integration-tests/__fixtures__/index.ts b/packages/fulfillment/integration-tests/__fixtures__/index.ts new file mode 100644 index 0000000000..172f1ae6a4 --- /dev/null +++ b/packages/fulfillment/integration-tests/__fixtures__/index.ts @@ -0,0 +1 @@ +// noop diff --git a/packages/fulfillment/integration-tests/__tests__/index.ts b/packages/fulfillment/integration-tests/__tests__/index.ts new file mode 100644 index 0000000000..333c84c1dd --- /dev/null +++ b/packages/fulfillment/integration-tests/__tests__/index.ts @@ -0,0 +1,5 @@ +describe("noop", function () { + it("should run", function () { + expect(true).toBe(true) + }) +}) diff --git a/packages/fulfillment/integration-tests/setup-env.js b/packages/fulfillment/integration-tests/setup-env.js new file mode 100644 index 0000000000..e8e2a6b17a --- /dev/null +++ b/packages/fulfillment/integration-tests/setup-env.js @@ -0,0 +1,6 @@ +if (typeof process.env.DB_TEMP_NAME === "undefined") { + const tempName = parseInt(process.env.JEST_WORKER_ID || "1") + process.env.DB_TEMP_NAME = `medusa-fulfillment-integration-${tempName}` +} + +process.env.MEDUSA_FULFILLMENT_DB_SCHEMA = "public" diff --git a/packages/fulfillment/integration-tests/setup.js b/packages/fulfillment/integration-tests/setup.js new file mode 100644 index 0000000000..43f99aab4a --- /dev/null +++ b/packages/fulfillment/integration-tests/setup.js @@ -0,0 +1,3 @@ +import { JestUtils } from "medusa-test-utils" + +JestUtils.afterAllHookDropDatabase() diff --git a/packages/fulfillment/integration-tests/utils/database.ts b/packages/fulfillment/integration-tests/utils/database.ts new file mode 100644 index 0000000000..118464d4d7 --- /dev/null +++ b/packages/fulfillment/integration-tests/utils/database.ts @@ -0,0 +1,18 @@ +import { TestDatabaseUtils } from "medusa-test-utils" + +import * as Models from "@models" + +const pathToMigrations = "../../src/migrations" +const mikroOrmEntities = Models as unknown as any[] + +export const MikroOrmWrapper = TestDatabaseUtils.getMikroOrmWrapper( + mikroOrmEntities, + pathToMigrations +) + +export const MikroOrmConfig = TestDatabaseUtils.getMikroOrmConfig( + mikroOrmEntities, + pathToMigrations +) + +export const DB_URL = TestDatabaseUtils.getDatabaseURL() diff --git a/packages/fulfillment/integration-tests/utils/get-init-module-config.ts b/packages/fulfillment/integration-tests/utils/get-init-module-config.ts new file mode 100644 index 0000000000..5ebb110c29 --- /dev/null +++ b/packages/fulfillment/integration-tests/utils/get-init-module-config.ts @@ -0,0 +1,33 @@ +import { Modules, ModulesDefinition } from "@medusajs/modules-sdk" + +import { DB_URL } from "./database" + +export function getInitModuleConfig() { + const moduleOptions = { + defaultAdapterOptions: { + database: { + clientUrl: DB_URL, + schema: process.env.MEDUSA_FULFILLMENT_DB_SCHEMA, + }, + }, + } + + const injectedDependencies = {} + + const modulesConfig_ = { + [Modules.FULFILLMENT]: { + definition: ModulesDefinition[Modules.FULFILLMENT], + options: moduleOptions, + }, + } + + return { + injectedDependencies, + modulesConfig: modulesConfig_, + databaseConfig: { + clientUrl: DB_URL, + schema: process.env.MEDUSA_FULFILLMENT_DB_SCHEMA, + }, + joinerConfig: [], + } +} diff --git a/packages/fulfillment/integration-tests/utils/index.ts b/packages/fulfillment/integration-tests/utils/index.ts new file mode 100644 index 0000000000..6b917ed30e --- /dev/null +++ b/packages/fulfillment/integration-tests/utils/index.ts @@ -0,0 +1 @@ +export * from "./database" diff --git a/packages/fulfillment/jest.config.js b/packages/fulfillment/jest.config.js new file mode 100644 index 0000000000..456054fe8a --- /dev/null +++ b/packages/fulfillment/jest.config.js @@ -0,0 +1,22 @@ +module.exports = { + moduleNameMapper: { + "^@models": "/src/models", + "^@services": "/src/services", + "^@repositories": "/src/repositories", + "^@types": "/src/types", + }, + transform: { + "^.+\\.[jt]s?$": [ + "ts-jest", + { + tsConfig: "tsconfig.spec.json", + isolatedModules: true, + }, + ], + }, + testEnvironment: `node`, + moduleFileExtensions: [`js`, `ts`], + modulePathIgnorePatterns: ["dist/"], + setupFiles: ["/integration-tests/setup-env.js"], + setupFilesAfterEnv: ["/integration-tests/setup.js"], +} diff --git a/packages/fulfillment/mikro-orm.config.dev.ts b/packages/fulfillment/mikro-orm.config.dev.ts new file mode 100644 index 0000000000..0cf4358c6c --- /dev/null +++ b/packages/fulfillment/mikro-orm.config.dev.ts @@ -0,0 +1,8 @@ +import * as entities from "./src/models" + +module.exports = { + entities: Object.values(entities), + schema: "public", + clientUrl: "postgres://postgres@localhost/medusa-fulfillment", + type: "postgresql", +} diff --git a/packages/fulfillment/package.json b/packages/fulfillment/package.json new file mode 100644 index 0000000000..94fbac4399 --- /dev/null +++ b/packages/fulfillment/package.json @@ -0,0 +1,61 @@ +{ + "name": "@medusajs/fulfillment", + "version": "0.1.0", + "description": "Medusa Fulfillment module", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "engines": { + "node": ">=16" + }, + "bin": { + "medusa-fulfillment-seed": "dist/scripts/bin/run-seed.js" + }, + "repository": { + "type": "git", + "url": "https://github.com/medusajs/medusa", + "directory": "packages/fulfillment" + }, + "publishConfig": { + "access": "public" + }, + "author": "Medusa", + "license": "MIT", + "scripts": { + "watch": "tsc --build --watch", + "watch:test": "tsc --build tsconfig.spec.json --watch", + "prepublishOnly": "cross-env NODE_ENV=production tsc --build && tsc-alias -p tsconfig.json", + "build": "rimraf dist && tsc --build && tsc-alias -p tsconfig.json", + "test": "jest --runInBand --bail --forceExit -- src/**/__tests__/**/*.ts", + "test:integration": "jest --runInBand --forceExit -- integration-tests/**/__tests__/**/*.ts", + "migration:generate": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:generate", + "migration:initial": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create --initial", + "migration:create": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:create", + "migration:up": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm migration:up", + "orm:cache:clear": " MIKRO_ORM_CLI=./mikro-orm.config.dev.ts mikro-orm cache:clear" + }, + "devDependencies": { + "@mikro-orm/cli": "5.9.7", + "cross-env": "^5.2.1", + "jest": "^29.6.3", + "medusa-test-utils": "^1.1.40", + "rimraf": "^3.0.2", + "ts-jest": "^29.1.1", + "ts-node": "^10.9.1", + "tsc-alias": "^1.8.6", + "typescript": "^5.1.6" + }, + "dependencies": { + "@medusajs/modules-sdk": "^1.12.4", + "@medusajs/types": "^1.11.8", + "@medusajs/utils": "^1.11.1", + "@mikro-orm/core": "5.9.7", + "@mikro-orm/migrations": "5.9.7", + "@mikro-orm/postgresql": "5.9.7", + "awilix": "^8.0.0", + "dotenv": "^16.1.4", + "knex": "2.4.2" + } +} diff --git a/packages/fulfillment/src/index.ts b/packages/fulfillment/src/index.ts new file mode 100644 index 0000000000..2567a38d8e --- /dev/null +++ b/packages/fulfillment/src/index.ts @@ -0,0 +1,14 @@ +import { moduleDefinition } from "./module-definition" +import { initializeFactory, Modules } from "@medusajs/modules-sdk" + +export * from "./types" +export * from "./models" +export * from "./services" + +export const initialize = initializeFactory({ + moduleName: Modules.FULFILLMENT, + moduleDefinition, +}) +export const runMigrations = moduleDefinition.runMigrations +export const revertMigration = moduleDefinition.revertMigration +export default moduleDefinition diff --git a/packages/fulfillment/src/joiner-config.ts b/packages/fulfillment/src/joiner-config.ts new file mode 100644 index 0000000000..cfddbd51a9 --- /dev/null +++ b/packages/fulfillment/src/joiner-config.ts @@ -0,0 +1,25 @@ +import { Modules } from "@medusajs/modules-sdk" +import { ModuleJoinerConfig } from "@medusajs/types" +import { MapToConfig } from "@medusajs/utils" + +// TODO manage the config + +export const LinkableKeys: Record = {} + +const entityLinkableKeysMap: MapToConfig = {} +Object.entries(LinkableKeys).forEach(([key, value]) => { + entityLinkableKeysMap[value] ??= [] + entityLinkableKeysMap[value].push({ + mapTo: key, + valueFrom: key.split("_").pop()!, + }) +}) + +export const entityNameToLinkableKeysMap: MapToConfig = entityLinkableKeysMap + +export const joinerConfig: ModuleJoinerConfig = { + serviceName: Modules.FULFILLMENT, + primaryKeys: ["id"], + linkableKeys: LinkableKeys, + alias: [], +} as ModuleJoinerConfig diff --git a/packages/fulfillment/src/models/fullfilment-set.ts b/packages/fulfillment/src/models/fullfilment-set.ts new file mode 100644 index 0000000000..2a9af29ecd --- /dev/null +++ b/packages/fulfillment/src/models/fullfilment-set.ts @@ -0,0 +1,56 @@ +import { DALUtils, generateEntityId } from "@medusajs/utils" + +import { + BeforeCreate, + Entity, + Filter, + Index, + OnInit, + OptionalProps, + PrimaryKey, + Property, +} from "@mikro-orm/core" +import { DAL } from "@medusajs/types" + +type FulfillmentSetOptionalProps = DAL.SoftDeletableEntityDateColumns + +@Entity() +@Filter(DALUtils.mikroOrmSoftDeletableFilterOptions) +export default class FulfillmentSet { + [OptionalProps]?: FulfillmentSetOptionalProps + + @PrimaryKey({ columnType: "text" }) + id: string + + @Property({ columnType: "text" }) + name: string + + @Property({ + onCreate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + created_at: Date + + @Property({ + onCreate: () => new Date(), + onUpdate: () => new Date(), + columnType: "timestamptz", + defaultRaw: "now()", + }) + updated_at: Date + + @Index({ name: "IDX_fulfillment_set_deleted_at" }) + @Property({ columnType: "timestamptz", nullable: true }) + deleted_at: Date | null = null + + @BeforeCreate() + onCreate() { + this.id = generateEntityId(this.id, "fuset") + } + + @OnInit() + onInit() { + this.id = generateEntityId(this.id, "fuset") + } +} diff --git a/packages/fulfillment/src/models/index.ts b/packages/fulfillment/src/models/index.ts new file mode 100644 index 0000000000..4a32567351 --- /dev/null +++ b/packages/fulfillment/src/models/index.ts @@ -0,0 +1 @@ +export { default as FulfillmentSet } from "./fullfilment-set" diff --git a/packages/fulfillment/src/module-definition.ts b/packages/fulfillment/src/module-definition.ts new file mode 100644 index 0000000000..db6f694b69 --- /dev/null +++ b/packages/fulfillment/src/module-definition.ts @@ -0,0 +1,44 @@ +import { ModuleExports } from "@medusajs/types" +import * as ModuleServices from "@services" +import { FulfillmentModuleService } from "@services" +import { Modules } from "@medusajs/modules-sdk" +import * as Models from "@models" +import * as ModuleModels from "@models" +import { ModulesSdkUtils } from "@medusajs/utils" +import * as ModuleRepositories from "@repositories" + +const migrationScriptOptions = { + moduleName: Modules.FULFILLMENT, + models: Models, + pathToMigrations: __dirname + "/migrations", +} + +const runMigrations = ModulesSdkUtils.buildMigrationScript( + migrationScriptOptions +) + +const revertMigration = ModulesSdkUtils.buildRevertMigrationScript( + migrationScriptOptions +) + +const containerLoader = ModulesSdkUtils.moduleContainerLoaderFactory({ + moduleModels: ModuleModels, + moduleRepositories: ModuleRepositories, + moduleServices: ModuleServices, +}) + +const connectionLoader = ModulesSdkUtils.mikroOrmConnectionLoaderFactory({ + moduleName: Modules.FULFILLMENT, + moduleModels: Object.values(Models), + migrationsPath: __dirname + "/migrations", +}) + +const service = FulfillmentModuleService +const loaders = [containerLoader, connectionLoader] as any + +export const moduleDefinition: ModuleExports = { + service, + loaders, + revertMigration, + runMigrations, +} diff --git a/packages/fulfillment/src/repositories/index.ts b/packages/fulfillment/src/repositories/index.ts new file mode 100644 index 0000000000..147c9cc259 --- /dev/null +++ b/packages/fulfillment/src/repositories/index.ts @@ -0,0 +1 @@ +export { MikroOrmBaseRepository as BaseRepository } from "@medusajs/utils" diff --git a/packages/fulfillment/src/scripts/bin/run-seed.ts b/packages/fulfillment/src/scripts/bin/run-seed.ts new file mode 100644 index 0000000000..5fa19060a0 --- /dev/null +++ b/packages/fulfillment/src/scripts/bin/run-seed.ts @@ -0,0 +1,29 @@ +#!/usr/bin/env node + +import { ModulesSdkUtils } from "@medusajs/utils" +import { Modules } from "@medusajs/modules-sdk" +import * as Models from "@models" +import { EOL } from "os" + +const args = process.argv +const path = args.pop() as string + +export default (async () => { + const { config } = await import("dotenv") + config() + if (!path) { + throw new Error( + `filePath is required.${EOL}Example: medusa-fulfillment-seed ` + ) + } + + const run = ModulesSdkUtils.buildSeedScript({ + moduleName: Modules.FULFILLMENT, + models: Models, + pathToMigrations: __dirname + "/../../migrations", + seedHandler: async ({ manager, data }) => { + // TODO: Add seed logic + }, + }) + await run({ path }) +})() diff --git a/packages/fulfillment/src/services/__tests__/noop.ts b/packages/fulfillment/src/services/__tests__/noop.ts new file mode 100644 index 0000000000..333c84c1dd --- /dev/null +++ b/packages/fulfillment/src/services/__tests__/noop.ts @@ -0,0 +1,5 @@ +describe("noop", function () { + it("should run", function () { + expect(true).toBe(true) + }) +}) diff --git a/packages/fulfillment/src/services/fulfillment-module-service.ts b/packages/fulfillment/src/services/fulfillment-module-service.ts new file mode 100644 index 0000000000..0236198985 --- /dev/null +++ b/packages/fulfillment/src/services/fulfillment-module-service.ts @@ -0,0 +1,91 @@ +import { + Context, + DAL, + FulfillmentTypes, + IFulfillmentModuleService, + InternalModuleDeclaration, + ModuleJoinerConfig, + ModulesSdkTypes, +} from "@medusajs/types" +import { InjectTransactionManager, ModulesSdkUtils } from "@medusajs/utils" + +import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config" +import { FulfillmentSet } from "@models" + +type InjectedDependencies = { + baseRepository: DAL.RepositoryService + fulfillmentService: ModulesSdkTypes.InternalModuleService +} + +export default class FulfillmentModuleService< + TEntity extends FulfillmentSet = FulfillmentSet + > + extends ModulesSdkUtils.abstractModuleServiceFactory< + InjectedDependencies, + any, // TODO Create appropriate DTO + {} + >(FulfillmentSet, [], entityNameToLinkableKeysMap) + implements IFulfillmentModuleService +{ + protected baseRepository_: DAL.RepositoryService + protected readonly fulfillmentService_: ModulesSdkTypes.InternalModuleService + + constructor( + { baseRepository, fulfillmentService }: InjectedDependencies, + protected readonly moduleDeclaration: InternalModuleDeclaration + ) { + // @ts-ignore + super(...arguments) + this.baseRepository_ = baseRepository + this.fulfillmentService_ = fulfillmentService + } + + __joinerConfig(): ModuleJoinerConfig { + return joinerConfig + } + + create( + data: any[], + sharedContext?: Context + ): Promise + + create( + data: any, + sharedContext?: Context + ): Promise + + // TODO Implement the methods from the interface and change type + @InjectTransactionManager("baseRepository_") + async create( + data: any[] | any, + sharedContext?: Context + ): Promise< + FulfillmentTypes.FulfillmentDTO | FulfillmentTypes.FulfillmentDTO[] + > { + return await Promise.resolve( + [] as FulfillmentTypes.FulfillmentDTO[] | FulfillmentTypes.FulfillmentDTO + ) + } + + // TODO Implement the methods from the interface and change type + update( + data: any[], + sharedContext?: Context + ): Promise + update( + data: any, + sharedContext?: Context + ): Promise + + @InjectTransactionManager("baseRepository_") + async update( + data: any, + sharedContext?: Context + ): Promise< + FulfillmentTypes.FulfillmentDTO | FulfillmentTypes.FulfillmentDTO[] + > { + return await Promise.resolve( + [] as FulfillmentTypes.FulfillmentDTO[] | FulfillmentTypes.FulfillmentDTO + ) + } +} diff --git a/packages/fulfillment/src/services/index.ts b/packages/fulfillment/src/services/index.ts new file mode 100644 index 0000000000..856e2bbbf6 --- /dev/null +++ b/packages/fulfillment/src/services/index.ts @@ -0,0 +1 @@ +export { default as FulfillmentModuleService } from "./fulfillment-module-service" diff --git a/packages/fulfillment/src/types/index.ts b/packages/fulfillment/src/types/index.ts new file mode 100644 index 0000000000..fdac085753 --- /dev/null +++ b/packages/fulfillment/src/types/index.ts @@ -0,0 +1,6 @@ +import { IEventBusModuleService, Logger } from "@medusajs/types" + +export type InitializeModuleInjectableDependencies = { + logger?: Logger + eventBusService?: IEventBusModuleService +} diff --git a/packages/fulfillment/tsconfig.json b/packages/fulfillment/tsconfig.json new file mode 100644 index 0000000000..4b79cd6032 --- /dev/null +++ b/packages/fulfillment/tsconfig.json @@ -0,0 +1,37 @@ +{ + "compilerOptions": { + "lib": ["es2020"], + "target": "es2020", + "outDir": "./dist", + "esModuleInterop": true, + "declaration": true, + "module": "commonjs", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "sourceMap": false, + "noImplicitReturns": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "noImplicitThis": true, + "allowJs": true, + "skipLibCheck": true, + "downlevelIteration": true, // to use ES5 specific tooling + "baseUrl": ".", + "resolveJsonModule": true, + "paths": { + "@models": ["./src/models"], + "@services": ["./src/services"], + "@repositories": ["./src/repositories"], + "@types": ["./src/types"] + } + }, + "include": ["src"], + "exclude": [ + "dist", + "./src/**/__tests__", + "./src/**/__mocks__", + "./src/**/__fixtures__", + "node_modules" + ] +} diff --git a/packages/fulfillment/tsconfig.spec.json b/packages/fulfillment/tsconfig.spec.json new file mode 100644 index 0000000000..48e47e8cbb --- /dev/null +++ b/packages/fulfillment/tsconfig.spec.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "include": ["src", "integration-tests"], + "exclude": ["node_modules", "dist"], + "compilerOptions": { + "sourceMap": true + } +} diff --git a/packages/modules-sdk/src/definitions.ts b/packages/modules-sdk/src/definitions.ts index 4e58fa5768..aeb8d228d0 100644 --- a/packages/modules-sdk/src/definitions.ts +++ b/packages/modules-sdk/src/definitions.ts @@ -19,6 +19,7 @@ export enum Modules { PRODUCT = "productService", PROMOTION = "promotion", SALES_CHANNEL = "salesChannel", + FULFILLMENT = "fulfillment", STOCK_LOCATION = "stockLocationService", USER = "user", WORKFLOW_ENGINE = "workflows", @@ -37,6 +38,7 @@ export enum ModuleRegistrationName { PRODUCT = "productModuleService", PROMOTION = "promotionModuleService", SALES_CHANNEL = "salesChannelModuleService", + FULFILLMENT = "fulfillmentModuleService", STOCK_LOCATION = "stockLocationService", USER = "userModuleService", WORKFLOW_ENGINE = "workflowsModuleService", @@ -56,6 +58,7 @@ export const MODULE_PACKAGE_NAMES = { [Modules.PRODUCT]: "@medusajs/product", [Modules.PROMOTION]: "@medusajs/promotion", [Modules.SALES_CHANNEL]: "@medusajs/sales-channel", + [Modules.FULFILLMENT]: "@medusajs/fulfillment", [Modules.STOCK_LOCATION]: "@medusajs/stock-location", [Modules.USER]: "@medusajs/user", [Modules.WORKFLOW_ENGINE]: "@medusajs/workflow-engine-inmemory", @@ -195,6 +198,19 @@ export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } = resources: MODULE_RESOURCE_TYPE.SHARED, }, }, + [Modules.FULFILLMENT]: { + key: Modules.FULFILLMENT, + registrationName: ModuleRegistrationName.FULFILLMENT, + defaultPackage: false, + label: upperCaseFirst(ModuleRegistrationName.FULFILLMENT), + isRequired: false, + isQueryable: true, + dependencies: ["logger", "eventBusService"], + defaultModuleDeclaration: { + scope: MODULE_SCOPE.INTERNAL, + resources: MODULE_RESOURCE_TYPE.SHARED, + }, + }, [Modules.CART]: { key: Modules.CART, registrationName: ModuleRegistrationName.CART, diff --git a/packages/modules-sdk/src/index.ts b/packages/modules-sdk/src/index.ts index 7aacd8daef..843aa56371 100644 --- a/packages/modules-sdk/src/index.ts +++ b/packages/modules-sdk/src/index.ts @@ -5,4 +5,4 @@ export * from "./medusa-app" export * from "./medusa-module" export * from "./remote-link" export * from "./remote-query" - +export * from "./utils/initialize-factory" diff --git a/packages/modules-sdk/src/utils/index.ts b/packages/modules-sdk/src/utils/index.ts index d1470bdcbc..9fc688e961 100644 --- a/packages/modules-sdk/src/utils/index.ts +++ b/packages/modules-sdk/src/utils/index.ts @@ -1,2 +1,3 @@ export * from "./clean-graphql-schema" export * from "./graphql-schema-to-fields" +export * from "./initialize-factory" diff --git a/packages/modules-sdk/src/utils/initialize-factory.ts b/packages/modules-sdk/src/utils/initialize-factory.ts new file mode 100644 index 0000000000..6230ee0e3a --- /dev/null +++ b/packages/modules-sdk/src/utils/initialize-factory.ts @@ -0,0 +1,44 @@ +import { + ExternalModuleDeclaration, + InternalModuleDeclaration, + ModuleExports, + ModuleServiceInitializeCustomDataLayerOptions, + ModuleServiceInitializeOptions, +} from "@medusajs/types" +import { MODULE_PACKAGE_NAMES } from "../definitions" +import { MedusaModule } from "../medusa-module" + +/** + * Generate a initialize module factory that is exported by the module to be initialized manually + * + * @param moduleName + * @param moduleDefinition + */ +export function initializeFactory({ + moduleName, + moduleDefinition, +}: { + moduleName: string + moduleDefinition: ModuleExports +}) { + return async ( + options?: + | ModuleServiceInitializeOptions + | ModuleServiceInitializeCustomDataLayerOptions + | ExternalModuleDeclaration + | InternalModuleDeclaration, + injectedDependencies?: any + ) => { + const loaded = await MedusaModule.bootstrap({ + moduleKey: moduleName, + defaultPath: MODULE_PACKAGE_NAMES[moduleName], + declaration: options as + | InternalModuleDeclaration + | ExternalModuleDeclaration, + injectedDependencies, + moduleExports: moduleDefinition, + }) + + return loaded[moduleName] as T + } +} diff --git a/packages/types/src/bundles.ts b/packages/types/src/bundles.ts index 9928c1ca1c..d8d91dbc71 100644 --- a/packages/types/src/bundles.ts +++ b/packages/types/src/bundles.ts @@ -6,6 +6,7 @@ export * as CustomerTypes from "./customer" export * as DAL from "./dal" export * as EventBusTypes from "./event-bus" export * as FeatureFlagTypes from "./feature-flag" +export * as FulfillmentTypes from "./fulfillment" export * as InventoryTypes from "./inventory" export * as LoggerTypes from "./logger" export * as ModulesSdkTypes from "./modules-sdk" diff --git a/packages/types/src/fulfillment/common.ts b/packages/types/src/fulfillment/common.ts new file mode 100644 index 0000000000..bcc8e44f07 --- /dev/null +++ b/packages/types/src/fulfillment/common.ts @@ -0,0 +1,4 @@ +export interface FulfillmentDTO { + id: string + name: string +} diff --git a/packages/types/src/fulfillment/index.ts b/packages/types/src/fulfillment/index.ts new file mode 100644 index 0000000000..0c73656566 --- /dev/null +++ b/packages/types/src/fulfillment/index.ts @@ -0,0 +1,3 @@ +export * from "./common" +export * from "./mutations" +export * from "./service" diff --git a/packages/types/src/fulfillment/mutations.ts b/packages/types/src/fulfillment/mutations.ts new file mode 100644 index 0000000000..336ce12bb9 --- /dev/null +++ b/packages/types/src/fulfillment/mutations.ts @@ -0,0 +1 @@ +export {} diff --git a/packages/types/src/fulfillment/service.ts b/packages/types/src/fulfillment/service.ts new file mode 100644 index 0000000000..da5cbfca6c --- /dev/null +++ b/packages/types/src/fulfillment/service.ts @@ -0,0 +1,58 @@ +import { IModuleService } from "../modules-sdk" +import { FulfillmentDTO } from "./common" +import { FindConfig } from "../common" +import { Context } from "../shared-context" +import { RestoreReturn, SoftDeleteReturn } from "../dal" + +export interface IFulfillmentModuleService extends IModuleService { + create( + data: any[], // TODO Create appropriate DTO + sharedContext?: Context + ): Promise + create( + data: any, // TODO Create appropriate DTO + sharedContext?: Context + ): Promise + + update( + data: any[], // TODO Create appropriate DTO + sharedContext?: Context + ): Promise + update( + data: any, // TODO Create appropriate DTO + sharedContext?: Context + ): Promise + + delete(ids: string[], sharedContext?: Context): Promise + delete(id: string, sharedContext?: Context): Promise + + retrieve( + id: string, + config?: FindConfig, + sharedContext?: Context + ): Promise + + list( + filters?: any, // TODO Create appropriate filter type + config?: FindConfig, + sharedContext?: Context + ): Promise + + listAndCount( + filters?: any, // TODO Create appropriate filter type + config?: FindConfig, + sharedContext?: Context + ): Promise<[FulfillmentDTO[], number]> + + softDelete( + fulfillmentIds: string[], + config?: SoftDeleteReturn, + sharedContext?: Context + ): Promise | void> + + restore( + fulfillmentIds: string[], + config?: RestoreReturn, + sharedContext?: Context + ): Promise | void> +} diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 93a1f99077..5d7d823b6e 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -8,6 +8,7 @@ export * from "./customer" export * from "./dal" export * from "./event-bus" export * from "./feature-flag" +export * from "./fulfillment" export * from "./file-service" export * from "./inventory" export * from "./joiner" diff --git a/packages/utils/src/modules-sdk/index.ts b/packages/utils/src/modules-sdk/index.ts index 8837a26b11..5e2011276c 100644 --- a/packages/utils/src/modules-sdk/index.ts +++ b/packages/utils/src/modules-sdk/index.ts @@ -2,6 +2,7 @@ export * from "./load-module-database-config" export * from "./decorators" export * from "./build-query" export * from "./loaders/mikro-orm-connection-loader" +export * from "./loaders/mikro-orm-connection-loader-factory" export * from "./loaders/container-loader-factory" export * from "./create-pg-connection" export * from "./migration-scripts" diff --git a/packages/utils/src/modules-sdk/loaders/mikro-orm-connection-loader-factory.ts b/packages/utils/src/modules-sdk/loaders/mikro-orm-connection-loader-factory.ts new file mode 100644 index 0000000000..84ff065225 --- /dev/null +++ b/packages/utils/src/modules-sdk/loaders/mikro-orm-connection-loader-factory.ts @@ -0,0 +1,34 @@ +import { InternalModuleDeclaration, LoaderOptions } from "@medusajs/types" +import { mikroOrmConnectionLoader } from "./mikro-orm-connection-loader" + +/** + * Factory for creating a MikroORM connection loader for the modules + * + * @param moduleName + * @param moduleModels + * @param migrationsPath + */ +export function mikroOrmConnectionLoaderFactory({ + moduleName, + moduleModels, + migrationsPath, +}: { + moduleName: string + moduleModels: any[] + migrationsPath?: string +}): any { + return async ( + { options, container, logger }: LoaderOptions, + moduleDeclaration?: InternalModuleDeclaration + ): Promise => { + await mikroOrmConnectionLoader({ + moduleName, + entities: moduleModels, + container, + options, + moduleDeclaration, + logger, + pathToMigrations: migrationsPath ?? "", + }) + } +} diff --git a/packages/utils/src/modules-sdk/loaders/mikro-orm-connection-loader.ts b/packages/utils/src/modules-sdk/loaders/mikro-orm-connection-loader.ts index 09c2704e2b..480743f315 100644 --- a/packages/utils/src/modules-sdk/loaders/mikro-orm-connection-loader.ts +++ b/packages/utils/src/modules-sdk/loaders/mikro-orm-connection-loader.ts @@ -11,6 +11,16 @@ import { ContainerRegistrationKeys, MedusaError } from "../../common" import { mikroOrmCreateConnection } from "../../dal" import { loadDatabaseConfig } from "../load-module-database-config" +/** + * Load a MikroORM connection into the container + * + * @param moduleName + * @param container + * @param options + * @param moduleDeclaration + * @param entities + * @param pathToMigrations + */ export async function mikroOrmConnectionLoader({ moduleName, container, diff --git a/yarn.lock b/yarn.lock index 3aca9234b3..73d5c6e5d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8140,6 +8140,33 @@ __metadata: languageName: unknown linkType: soft +"@medusajs/fulfillment@workspace:packages/fulfillment": + version: 0.0.0-use.local + resolution: "@medusajs/fulfillment@workspace:packages/fulfillment" + dependencies: + "@medusajs/modules-sdk": ^1.12.4 + "@medusajs/types": ^1.11.8 + "@medusajs/utils": ^1.11.1 + "@mikro-orm/cli": 5.9.7 + "@mikro-orm/core": 5.9.7 + "@mikro-orm/migrations": 5.9.7 + "@mikro-orm/postgresql": 5.9.7 + awilix: ^8.0.0 + cross-env: ^5.2.1 + dotenv: ^16.1.4 + jest: ^29.6.3 + knex: 2.4.2 + medusa-test-utils: ^1.1.40 + rimraf: ^3.0.2 + ts-jest: ^29.1.1 + ts-node: ^10.9.1 + tsc-alias: ^1.8.6 + typescript: ^5.1.6 + bin: + medusa-fulfillment-seed: dist/scripts/bin/run-seed.js + languageName: unknown + linkType: soft + "@medusajs/icons@^1.1.0, @medusajs/icons@^1.2.0, @medusajs/icons@workspace:^, @medusajs/icons@workspace:packages/design-system/icons": version: 0.0.0-use.local resolution: "@medusajs/icons@workspace:packages/design-system/icons"