Skip to content

Commit

Permalink
feat: Region Module (basic CRUD) (#6315)
Browse files Browse the repository at this point in the history
  • Loading branch information
olivermrbl authored Feb 5, 2024
1 parent ede221d commit 823b98a
Show file tree
Hide file tree
Showing 49 changed files with 2,716 additions and 13 deletions.
5 changes: 3 additions & 2 deletions packages/core-flows/src/handlers/region/find-region.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { MedusaError } from "@medusajs/utils"
import { RegionTypes } from "@medusajs/types"
import { MedusaError } from "@medusajs/utils"
import { isDefined } from "medusa-core-utils"

import { WorkflowArguments } from "@medusajs/workflows-sdk"

type RegionResultDTO = {
region_id?: string
region?: RegionTypes.RegionDTO
// TODO: Replace with RegionDTO from Region Module
region?: RegionTypes.RegionDTO__legacy
}

type HandlerInputData = {
Expand Down
16 changes: 16 additions & 0 deletions packages/modules-sdk/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export enum Modules {
CART = "cart",
CUSTOMER = "customer",
PAYMENT = "payment",
REGION = "region",
}

export enum ModuleRegistrationName {
Expand All @@ -37,6 +38,7 @@ export enum ModuleRegistrationName {
CART = "cartModuleService",
CUSTOMER = "customerModuleService",
PAYMENT = "paymentModuleService",
REGION = "regionModuleService",
}

export const MODULE_PACKAGE_NAMES = {
Expand All @@ -54,6 +56,7 @@ export const MODULE_PACKAGE_NAMES = {
[Modules.CART]: "@medusajs/cart",
[Modules.CUSTOMER]: "@medusajs/customer",
[Modules.PAYMENT]: "@medusajs/payment",
[Modules.REGION]: "@medusajs/region",
}

export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } =
Expand Down Expand Up @@ -228,6 +231,19 @@ export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } =
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
[Modules.REGION]: {
key: Modules.REGION,
registrationName: ModuleRegistrationName.REGION,
defaultPackage: false,
label: upperCaseFirst(ModuleRegistrationName.REGION),
isRequired: false,
isQueryable: true,
dependencies: ["logger"],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
}

export const MODULE_DEFINITIONS: ModuleDefinition[] =
Expand Down
6 changes: 6 additions & 0 deletions packages/region/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/dist
node_modules
.DS_store
.env*
.env
*.sql
1 change: 1 addition & 0 deletions packages/region/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Region Module
101 changes: 101 additions & 0 deletions packages/region/integration-tests/__tests__/region-module.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { Modules } from "@medusajs/modules-sdk"
import { IRegionModuleService } from "@medusajs/types"
import { DefaultsUtils } from "@medusajs/utils"
import { initModules } from "medusa-test-utils"
import { MikroOrmWrapper } from "../utils"
import { getInitModuleConfig } from "../utils/get-init-module-config"

jest.setTimeout(30000)

describe("Region Module Service", () => {
let service: IRegionModuleService
let shutdownFunc: () => Promise<void>

beforeEach(async () => {
await MikroOrmWrapper.setupDatabase()

const initModulesConfig = getInitModuleConfig()
const { medusaApp, shutdown } = await initModules(initModulesConfig)
service = medusaApp.modules[Modules.REGION]

shutdownFunc = shutdown
})

afterEach(async () => {
await MikroOrmWrapper.clearDatabase()
await shutdownFunc()
})

it("should create countries and currencies on application start", async () => {
const countries = await service.listCountries()
const currencies = await service.listCurrencies()

expect(countries.length).toBeGreaterThan(0)
expect(currencies.length).toBeGreaterThan(0)
})

it("should create countries added to default ones", async () => {
const [, count] = await service.listAndCountCountries()
const initialCountries = DefaultsUtils.defaultCountries.length

expect(count).toEqual(initialCountries)

DefaultsUtils.defaultCountries.push({
name: "Dogecoin",
alpha2: "DOGE",
alpha3: "DOGE",
numeric: "420",
})

await service.createDefaultCountriesAndCurrencies()

const [, newCount] = await service.listAndCountCountries()
expect(newCount).toEqual(initialCountries + 1)
})

it("should create and list a region", async () => {
const createdRegion = await service.create({
name: "Europe",
currency_code: "EUR",
})

expect(createdRegion).toEqual(
expect.objectContaining({
id: createdRegion.id,
name: "Europe",
currency_code: "EUR",
currency: expect.objectContaining({
code: "eur",
name: "Euro",
}),
countries: [],
})
)

const region = await service.retrieve(createdRegion.id, {
relations: ["currency", "countries"],
})

expect(region).toEqual(
expect.objectContaining({
id: region.id,
name: "Europe",
currency_code: "EUR",
currency: expect.objectContaining({
code: "eur",
name: "Euro",
}),
countries: [],
})
)
})

it("should fail when currency does not exist", async () => {
await expect(
service.create({
name: "Europe",
currency_code: "DOGECOIN",
})
).rejects.toThrowError("Currency with code: DOGECOIN was not found")
})
})
6 changes: 6 additions & 0 deletions packages/region/integration-tests/setup-env.js
Original file line number Diff line number Diff line change
@@ -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-region-integration-${tempName}`
}

process.env.MEDUSA_REGION_DB_SCHEMA = "public"
3 changes: 3 additions & 0 deletions packages/region/integration-tests/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { JestUtils } from "medusa-test-utils"

JestUtils.afterAllHookDropDatabase()
6 changes: 6 additions & 0 deletions packages/region/integration-tests/utils/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ModuleServiceInitializeOptions } from "@medusajs/types"

export const databaseOptions: ModuleServiceInitializeOptions["database"] = {
schema: "public",
clientUrl: "medusa-region-test",
}
18 changes: 18 additions & 0 deletions packages/region/integration-tests/utils/database.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { TestDatabaseUtils } from "medusa-test-utils"

import * as RegionModels from "@models"

const pathToMigrations = "../../src/migrations"
const mikroOrmEntities = RegionModels as unknown as any[]

export const MikroOrmWrapper = TestDatabaseUtils.getMikroOrmWrapper(
mikroOrmEntities,
pathToMigrations
)

export const MikroOrmConfig = TestDatabaseUtils.getMikroOrmConfig(
mikroOrmEntities,
pathToMigrations
)

export const DB_URL = TestDatabaseUtils.getDatabaseURL()
33 changes: 33 additions & 0 deletions packages/region/integration-tests/utils/get-init-module-config.ts
Original file line number Diff line number Diff line change
@@ -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_REGION_DB_SCHEMA,
},
},
}

const injectedDependencies = {}

const modulesConfig_ = {
[Modules.REGION]: {
definition: ModulesDefinition[Modules.REGION],
options: moduleOptions,
},
}

return {
injectedDependencies,
modulesConfig: modulesConfig_,
databaseConfig: {
clientUrl: DB_URL,
schema: process.env.MEDUSA_REGION_DB_SCHEMA,
},
joinerConfig: [],
}
}
3 changes: 3 additions & 0 deletions packages/region/integration-tests/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./config"
export * from "./database"

22 changes: 22 additions & 0 deletions packages/region/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module.exports = {
moduleNameMapper: {
"^@models": "<rootDir>/src/models",
"^@services": "<rootDir>/src/services",
"^@repositories": "<rootDir>/src/repositories",
"^@types": "<rootDir>/src/types",
},
transform: {
"^.+\\.[jt]s?$": [
"ts-jest",
{
tsConfig: "tsconfig.spec.json",
isolatedModules: true,
},
],
},
testEnvironment: `node`,
moduleFileExtensions: [`js`, `ts`],
modulePathIgnorePatterns: ["dist/"],
setupFiles: ["<rootDir>/integration-tests/setup-env.js"],
setupFilesAfterEnv: ["<rootDir>/integration-tests/setup.js"],
}
8 changes: 8 additions & 0 deletions packages/region/mikro-orm.config.dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import * as entities from "./src/models"

module.exports = {
entities: Object.values(entities),
schema: "public",
clientUrl: "postgres://postgres@localhost/medusa-region",
type: "postgresql",
}
61 changes: 61 additions & 0 deletions packages/region/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
{
"name": "@medusajs/region",
"version": "0.1.0",
"description": "Medusa Region module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"files": [
"dist"
],
"engines": {
"node": ">=16"
},
"bin": {
"medusa-region-seed": "dist/scripts/bin/run-seed.js"
},
"repository": {
"type": "git",
"url": "https://github.com/medusajs/medusa",
"directory": "packages/region"
},
"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": "workspace:^",
"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"
}
}
28 changes: 28 additions & 0 deletions packages/region/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Modules } from "@medusajs/modules-sdk"
import { ModulesSdkUtils } from "@medusajs/utils"

import * as RegionModels from "@models"

import { moduleDefinition } from "./module-definition"

export default moduleDefinition

const migrationScriptOptions = {
moduleName: Modules.REGION,
models: RegionModels,
pathToMigrations: __dirname + "/migrations",
}

export const runMigrations = ModulesSdkUtils.buildMigrationScript(
migrationScriptOptions
)
export const revertMigration = ModulesSdkUtils.buildRevertMigrationScript(
migrationScriptOptions
)

export * from "./initialize"
export * from "./loaders"
export * from "./models"
export * from "./services"
export * from "./types"

Loading

0 comments on commit 823b98a

Please sign in to comment.