fix(utils): define link alias + pluralize (#8070)

What:
 * Fix alias of models that have "compound names": eg "related_product"
 * `deleteCascade` option
 * Package to pluralize english words correctly
This commit is contained in:
Carlos R. L. Rodrigues
2024-07-10 19:37:14 -03:00
committed by GitHub
parent 256912f392
commit f460348280
6 changed files with 129 additions and 32 deletions
@@ -1,8 +1,9 @@
import { medusaIntegrationTestRunner } from "medusa-test-utils"
import CurrencyModule from "@medusajs/currency"
import { MedusaModule } from "@medusajs/modules-sdk"
import RegionModule from "@medusajs/region"
import { defineLink } from "@medusajs/utils"
import { MedusaModule } from "@medusajs/modules-sdk"
jest.setTimeout(50000)
@@ -46,6 +47,7 @@ medusaIntegrationTestRunner({
args: {
methodSuffix: "Currencies",
},
deleteCascade: false,
},
{
serviceName: "region",
@@ -55,6 +57,94 @@ medusaIntegrationTestRunner({
args: {
methodSuffix: "Regions",
},
deleteCascade: false,
},
],
extends: [
{
serviceName: "currency",
fieldAlias: {
region: "region_link.region",
},
relationship: {
serviceName: "currencyCurrencyRegionRegionLink",
primaryKey: "currency_code",
foreignKey: "code",
alias: "region_link",
isList: false,
},
},
{
serviceName: "region",
fieldAlias: {
currency: "currency_link.currency",
},
relationship: {
serviceName: "currencyCurrencyRegionRegionLink",
primaryKey: "region_id",
foreignKey: "id",
alias: "currency_link",
isList: false,
},
},
],
})
})
it("should flag deleteCascade in the link definition", async () => {
const currencyLinks = CurrencyModule.linkable
const regionLinks = RegionModule.linkable
const link = defineLink(
{
linkable: currencyLinks.currency,
deleteCascade: true,
},
regionLinks.region
)
const linkDefinition = MedusaModule.getCustomLinks()
.map((linkDefinition: any) => {
const definition = linkDefinition(
MedusaModule.getAllJoinerConfigs()
)
return definition.serviceName === link.serviceName && definition
})
.filter(Boolean)[0]
expect(link.serviceName).toEqual("currencyCurrencyRegionRegionLink")
expect(linkDefinition).toEqual({
serviceName: "currencyCurrencyRegionRegionLink",
isLink: true,
alias: [
{
name: ["currency_region"],
args: {
entity: "LinkCurrencyCurrencyRegionRegion",
},
},
],
primaryKeys: ["id", "currency_code", "region_id"],
relationships: [
{
serviceName: "currency",
primaryKey: "code",
foreignKey: "currency_code",
alias: "currency",
args: {
methodSuffix: "Currencies",
},
deleteCascade: true,
},
{
serviceName: "region",
primaryKey: "id",
foreignKey: "region_id",
alias: "region",
args: {
methodSuffix: "Regions",
},
deleteCascade: false,
},
],
extends: [
@@ -128,6 +218,7 @@ medusaIntegrationTestRunner({
args: {
methodSuffix: "Currencies",
},
deleteCascade: false,
},
{
serviceName: "region",
@@ -137,6 +228,7 @@ medusaIntegrationTestRunner({
args: {
methodSuffix: "Regions",
},
deleteCascade: false,
},
],
extends: [
+12
View File
@@ -353,6 +353,18 @@ export type Pluralize<Singular extends string> = Singular extends `${infer R}ey`
| `${infer R}z`
| `${infer R}o`
? `${Singular}es`
: Singular extends `${infer R}fe`
? `${R}ves`
: Singular extends `${infer R}ex` | `${infer R}ix`
? `${R}ices`
: Singular extends `${infer R}eau`
? `${R}eaux`
: Singular extends `${infer R}ieu`
? `${R}ieux`
: Singular extends `${infer R}sis`
? `${R}ses`
: Singular extends `${infer R}is`
? `${R}ises`
: `${Singular}s`
export type SnakeCase<S extends string> =
+1
View File
@@ -40,6 +40,7 @@
"dotenv": "^16.4.5",
"jsonwebtoken": "^9.0.2",
"knex": "2.4.2",
"pluralize": "^8.0.0",
"ulid": "^2.3.0"
},
"scripts": {
+5 -22
View File
@@ -1,27 +1,10 @@
import pluralizeEN from "pluralize"
/**
* Some library provide pluralize function with language specific rules.
* This is a simple implementation of pluralize function.
* Function to pluralize English words.
* @param word
*/
export function pluralize(word: string): string {
// Add basic rules for forming plurals
if (
//word.endsWith("s") ||
word.endsWith("sh") ||
word.endsWith("ss") ||
word.endsWith("ch") ||
word.endsWith("x") ||
word.endsWith("o") ||
word.endsWith("z")
) {
return word + "es"
} else if (word.endsWith("y") && !"aeiou".includes(word[word.length - 2])) {
return word.slice(0, -1) + "ies"
} else if (word.endsWith("es")) {
return word
} else if (word.endsWith("fe")) {
return word.slice(0, -2) + "ves"
} else {
return word + "s"
}
// TODO: Implement language specific pluralize function
return pluralizeEN(word)
}
@@ -1,5 +1,5 @@
import { LinkModulesExtraFields, ModuleJoinerConfig } from "@medusajs/types"
import { isObject, pluralize, toPascalCase } from "../common"
import { camelToSnakeCase, isObject, pluralize, toPascalCase } from "../common"
import { composeLinkName } from "../link"
export const DefineLinkSymbol = Symbol.for("DefineLink")
@@ -25,6 +25,7 @@ type CombinedSource = Record<any, any> & InputToJson
type InputOptions = {
linkable: CombinedSource | InputSource
isList?: boolean
deleteCascade?: boolean
}
type ExtraOptions = {
@@ -44,6 +45,7 @@ type ModuleLinkableKeyConfig = {
module: string
key: string
isList?: boolean
deleteCascade?: boolean
primaryKey: string
alias: string
shortcuts?: {
@@ -52,15 +54,15 @@ type ModuleLinkableKeyConfig = {
}
function isInputOptions(input: any): input is InputOptions {
return isObject(input) && "linkable" in input
return isObject(input) && input?.["linkable"]
}
function isInputSource(input: any): input is InputSource {
return (isObject(input) && "serviceName" in input) || "toJSON" in input
return (isObject(input) && input?.["serviceName"]) || input?.["toJSON"]
}
function isToJSON(input: any): input is InputToJson {
return isObject(input) && "toJSON" in input
return isObject(input) && input?.["toJSON"]
}
export function defineLink(
@@ -79,6 +81,7 @@ export function defineLink(
alias: source.field,
primaryKey: source.primaryKey,
isList: false,
deleteCascade: false,
module: source.serviceName,
}
} else if (isInputOptions(leftService)) {
@@ -91,6 +94,7 @@ export function defineLink(
alias: source.field,
primaryKey: source.primaryKey,
isList: leftService.isList ?? false,
deleteCascade: leftService.deleteCascade ?? false,
module: source.serviceName,
}
} else {
@@ -102,9 +106,10 @@ export function defineLink(
serviceBObj = {
key: source.linkable,
alias: source.field,
alias: camelToSnakeCase(source.field),
primaryKey: source.primaryKey,
isList: false,
deleteCascade: false,
module: source.serviceName,
}
} else if (isInputOptions(rightService)) {
@@ -114,9 +119,10 @@ export function defineLink(
serviceBObj = {
key: source.linkable,
alias: source.field,
alias: camelToSnakeCase(source.field),
primaryKey: source.primaryKey,
isList: rightService.isList ?? false,
deleteCascade: rightService.deleteCascade ?? false,
module: source.serviceName,
}
} else {
@@ -281,6 +287,7 @@ export function defineLink(
args: {
methodSuffix: serviceAMethodSuffix,
},
deleteCascade: serviceAObj.deleteCascade,
},
{
serviceName: serviceBObj.module,
@@ -290,6 +297,7 @@ export function defineLink(
args: {
methodSuffix: serviceBMethodSuffix,
},
deleteCascade: serviceBObj.deleteCascade,
},
],
extends: [
@@ -297,13 +305,13 @@ export function defineLink(
serviceName: serviceAObj.module,
fieldAlias: {
[serviceBObj.isList ? pluralize(aliasB) : aliasB]:
aliasB + "_link." + aliasB, //plural aliasA
aliasB + "_link." + aliasB,
},
relationship: {
serviceName: output.serviceName,
primaryKey: serviceAObj.key,
foreignKey: serviceAPrimaryKey,
alias: aliasB + "_link", // plural alias
alias: aliasB + "_link",
isList: serviceBObj.isList,
},
},
@@ -317,7 +325,7 @@ export function defineLink(
serviceName: output.serviceName,
primaryKey: serviceBObj.key,
foreignKey: serviceBPrimaryKey,
alias: aliasA + "_link", // plural alias
alias: aliasA + "_link",
isList: serviceAObj.isList,
},
},
+1
View File
@@ -5330,6 +5330,7 @@ __metadata:
jest: ^29.7.0
jsonwebtoken: ^9.0.2
knex: 2.4.2
pluralize: ^8.0.0
rimraf: ^5.0.1
ts-jest: ^29.1.1
typescript: ^5.1.6