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:
1 parent
256912f392
commit
f460348280
6 files changed
+129
-32
No files matched your search
@@ -1,8 +1,9 @@
|
|||||||
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
import { medusaIntegrationTestRunner } from "medusa-test-utils"
|
||||||
|
|
||||||
import CurrencyModule from "@medusajs/currency"
|
import CurrencyModule from "@medusajs/currency"
|
||||||
|
import { MedusaModule } from "@medusajs/modules-sdk"
|
||||||
import RegionModule from "@medusajs/region"
|
import RegionModule from "@medusajs/region"
|
||||||
import { defineLink } from "@medusajs/utils"
|
import { defineLink } from "@medusajs/utils"
|
||||||
import { MedusaModule } from "@medusajs/modules-sdk"
|
|
||||||
|
|
||||||
jest.setTimeout(50000)
|
jest.setTimeout(50000)
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ medusaIntegrationTestRunner({
|
|||||||
args: {
|
args: {
|
||||||
methodSuffix: "Currencies",
|
methodSuffix: "Currencies",
|
||||||
},
|
},
|
||||||
|
deleteCascade: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
serviceName: "region",
|
serviceName: "region",
|
||||||
@@ -55,6 +57,94 @@ medusaIntegrationTestRunner({
|
|||||||
args: {
|
args: {
|
||||||
methodSuffix: "Regions",
|
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: [
|
extends: [
|
||||||
@@ -128,6 +218,7 @@ medusaIntegrationTestRunner({
|
|||||||
args: {
|
args: {
|
||||||
methodSuffix: "Currencies",
|
methodSuffix: "Currencies",
|
||||||
},
|
},
|
||||||
|
deleteCascade: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
serviceName: "region",
|
serviceName: "region",
|
||||||
@@ -137,6 +228,7 @@ medusaIntegrationTestRunner({
|
|||||||
args: {
|
args: {
|
||||||
methodSuffix: "Regions",
|
methodSuffix: "Regions",
|
||||||
},
|
},
|
||||||
|
deleteCascade: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
extends: [
|
extends: [
|
||||||
|
|||||||
@@ -353,6 +353,18 @@ export type Pluralize<Singular extends string> = Singular extends `${infer R}ey`
|
|||||||
| `${infer R}z`
|
| `${infer R}z`
|
||||||
| `${infer R}o`
|
| `${infer R}o`
|
||||||
? `${Singular}es`
|
? `${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`
|
: `${Singular}s`
|
||||||
|
|
||||||
export type SnakeCase<S extends string> =
|
export type SnakeCase<S extends string> =
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"jsonwebtoken": "^9.0.2",
|
"jsonwebtoken": "^9.0.2",
|
||||||
"knex": "2.4.2",
|
"knex": "2.4.2",
|
||||||
|
"pluralize": "^8.0.0",
|
||||||
"ulid": "^2.3.0"
|
"ulid": "^2.3.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -1,27 +1,10 @@
|
|||||||
|
import pluralizeEN from "pluralize"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some library provide pluralize function with language specific rules.
|
* Function to pluralize English words.
|
||||||
* This is a simple implementation of pluralize function.
|
|
||||||
* @param word
|
* @param word
|
||||||
*/
|
*/
|
||||||
export function pluralize(word: string): string {
|
export function pluralize(word: string): string {
|
||||||
// Add basic rules for forming plurals
|
// TODO: Implement language specific pluralize function
|
||||||
if (
|
return pluralizeEN(word)
|
||||||
//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"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { LinkModulesExtraFields, ModuleJoinerConfig } from "@medusajs/types"
|
import { LinkModulesExtraFields, ModuleJoinerConfig } from "@medusajs/types"
|
||||||
import { isObject, pluralize, toPascalCase } from "../common"
|
import { camelToSnakeCase, isObject, pluralize, toPascalCase } from "../common"
|
||||||
import { composeLinkName } from "../link"
|
import { composeLinkName } from "../link"
|
||||||
|
|
||||||
export const DefineLinkSymbol = Symbol.for("DefineLink")
|
export const DefineLinkSymbol = Symbol.for("DefineLink")
|
||||||
@@ -25,6 +25,7 @@ type CombinedSource = Record<any, any> & InputToJson
|
|||||||
type InputOptions = {
|
type InputOptions = {
|
||||||
linkable: CombinedSource | InputSource
|
linkable: CombinedSource | InputSource
|
||||||
isList?: boolean
|
isList?: boolean
|
||||||
|
deleteCascade?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExtraOptions = {
|
type ExtraOptions = {
|
||||||
@@ -44,6 +45,7 @@ type ModuleLinkableKeyConfig = {
|
|||||||
module: string
|
module: string
|
||||||
key: string
|
key: string
|
||||||
isList?: boolean
|
isList?: boolean
|
||||||
|
deleteCascade?: boolean
|
||||||
primaryKey: string
|
primaryKey: string
|
||||||
alias: string
|
alias: string
|
||||||
shortcuts?: {
|
shortcuts?: {
|
||||||
@@ -52,15 +54,15 @@ type ModuleLinkableKeyConfig = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isInputOptions(input: any): input is InputOptions {
|
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 {
|
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 {
|
function isToJSON(input: any): input is InputToJson {
|
||||||
return isObject(input) && "toJSON" in input
|
return isObject(input) && input?.["toJSON"]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function defineLink(
|
export function defineLink(
|
||||||
@@ -79,6 +81,7 @@ export function defineLink(
|
|||||||
alias: source.field,
|
alias: source.field,
|
||||||
primaryKey: source.primaryKey,
|
primaryKey: source.primaryKey,
|
||||||
isList: false,
|
isList: false,
|
||||||
|
deleteCascade: false,
|
||||||
module: source.serviceName,
|
module: source.serviceName,
|
||||||
}
|
}
|
||||||
} else if (isInputOptions(leftService)) {
|
} else if (isInputOptions(leftService)) {
|
||||||
@@ -91,6 +94,7 @@ export function defineLink(
|
|||||||
alias: source.field,
|
alias: source.field,
|
||||||
primaryKey: source.primaryKey,
|
primaryKey: source.primaryKey,
|
||||||
isList: leftService.isList ?? false,
|
isList: leftService.isList ?? false,
|
||||||
|
deleteCascade: leftService.deleteCascade ?? false,
|
||||||
module: source.serviceName,
|
module: source.serviceName,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -102,9 +106,10 @@ export function defineLink(
|
|||||||
|
|
||||||
serviceBObj = {
|
serviceBObj = {
|
||||||
key: source.linkable,
|
key: source.linkable,
|
||||||
alias: source.field,
|
alias: camelToSnakeCase(source.field),
|
||||||
primaryKey: source.primaryKey,
|
primaryKey: source.primaryKey,
|
||||||
isList: false,
|
isList: false,
|
||||||
|
deleteCascade: false,
|
||||||
module: source.serviceName,
|
module: source.serviceName,
|
||||||
}
|
}
|
||||||
} else if (isInputOptions(rightService)) {
|
} else if (isInputOptions(rightService)) {
|
||||||
@@ -114,9 +119,10 @@ export function defineLink(
|
|||||||
|
|
||||||
serviceBObj = {
|
serviceBObj = {
|
||||||
key: source.linkable,
|
key: source.linkable,
|
||||||
alias: source.field,
|
alias: camelToSnakeCase(source.field),
|
||||||
primaryKey: source.primaryKey,
|
primaryKey: source.primaryKey,
|
||||||
isList: rightService.isList ?? false,
|
isList: rightService.isList ?? false,
|
||||||
|
deleteCascade: rightService.deleteCascade ?? false,
|
||||||
module: source.serviceName,
|
module: source.serviceName,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -281,6 +287,7 @@ export function defineLink(
|
|||||||
args: {
|
args: {
|
||||||
methodSuffix: serviceAMethodSuffix,
|
methodSuffix: serviceAMethodSuffix,
|
||||||
},
|
},
|
||||||
|
deleteCascade: serviceAObj.deleteCascade,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
serviceName: serviceBObj.module,
|
serviceName: serviceBObj.module,
|
||||||
@@ -290,6 +297,7 @@ export function defineLink(
|
|||||||
args: {
|
args: {
|
||||||
methodSuffix: serviceBMethodSuffix,
|
methodSuffix: serviceBMethodSuffix,
|
||||||
},
|
},
|
||||||
|
deleteCascade: serviceBObj.deleteCascade,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
extends: [
|
extends: [
|
||||||
@@ -297,13 +305,13 @@ export function defineLink(
|
|||||||
serviceName: serviceAObj.module,
|
serviceName: serviceAObj.module,
|
||||||
fieldAlias: {
|
fieldAlias: {
|
||||||
[serviceBObj.isList ? pluralize(aliasB) : aliasB]:
|
[serviceBObj.isList ? pluralize(aliasB) : aliasB]:
|
||||||
aliasB + "_link." + aliasB, //plural aliasA
|
aliasB + "_link." + aliasB,
|
||||||
},
|
},
|
||||||
relationship: {
|
relationship: {
|
||||||
serviceName: output.serviceName,
|
serviceName: output.serviceName,
|
||||||
primaryKey: serviceAObj.key,
|
primaryKey: serviceAObj.key,
|
||||||
foreignKey: serviceAPrimaryKey,
|
foreignKey: serviceAPrimaryKey,
|
||||||
alias: aliasB + "_link", // plural alias
|
alias: aliasB + "_link",
|
||||||
isList: serviceBObj.isList,
|
isList: serviceBObj.isList,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -317,7 +325,7 @@ export function defineLink(
|
|||||||
serviceName: output.serviceName,
|
serviceName: output.serviceName,
|
||||||
primaryKey: serviceBObj.key,
|
primaryKey: serviceBObj.key,
|
||||||
foreignKey: serviceBPrimaryKey,
|
foreignKey: serviceBPrimaryKey,
|
||||||
alias: aliasA + "_link", // plural alias
|
alias: aliasA + "_link",
|
||||||
isList: serviceAObj.isList,
|
isList: serviceAObj.isList,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in new issue
Block a user