feat(dashboard,admin-vite-plugin,admin-bundler,admin-sdk): Rework admin extensions and introduce custom fields API (#9338)

This commit is contained in:
Kasper Fabricius Kristensen
2024-10-09 13:44:40 +02:00
committed by GitHub
parent 35e69d32f2
commit d71343d6ab
159 changed files with 5266 additions and 2226 deletions

View File

@@ -0,0 +1,40 @@
import {
PRODUCT_CUSTOM_FIELD_DISPLAY_PATHS,
PRODUCT_CUSTOM_FIELD_DISPLAY_ZONES,
PRODUCT_CUSTOM_FIELD_FORM_CONFIG_PATHS,
PRODUCT_CUSTOM_FIELD_FORM_FIELD_PATHS,
PRODUCT_CUSTOM_FIELD_FORM_TABS,
PRODUCT_CUSTOM_FIELD_FORM_ZONES,
PRODUCT_CUSTOM_FIELD_LINK_PATHS,
PRODUCT_CUSTOM_FIELD_MODEL,
} from "./product"
export const CUSTOM_FIELD_MODELS = [PRODUCT_CUSTOM_FIELD_MODEL] as const
export const CUSTOM_FIELD_CONTAINER_ZONES = [
...PRODUCT_CUSTOM_FIELD_DISPLAY_ZONES,
] as const
export const CUSTOM_FIELD_FORM_ZONES = [
...PRODUCT_CUSTOM_FIELD_FORM_ZONES,
] as const
export const CUSTOM_FIELD_FORM_TABS = [
...PRODUCT_CUSTOM_FIELD_FORM_TABS,
] as const
export const CUSTOM_FIELD_FORM_CONFIG_PATHS = [
...PRODUCT_CUSTOM_FIELD_FORM_CONFIG_PATHS,
] as const
export const CUSTOM_FIELD_FORM_FIELD_PATHS = [
...PRODUCT_CUSTOM_FIELD_FORM_FIELD_PATHS,
] as const
export const CUSTOM_FIELD_DISPLAY_PATHS = [
...PRODUCT_CUSTOM_FIELD_DISPLAY_PATHS,
] as const
export const CUSTOM_FIELD_LINK_PATHS = [
...PRODUCT_CUSTOM_FIELD_LINK_PATHS,
] as const

View File

@@ -0,0 +1,3 @@
export * from "./product"
export * from "./types"
export * from "./utils"

View File

@@ -0,0 +1,48 @@
export const PRODUCT_CUSTOM_FIELD_MODEL = "product" as const
export const PRODUCT_CUSTOM_FIELD_FORM_ZONES = [
"create",
"edit",
"organize",
"attributes",
] as const
export const PRODUCT_CUSTOM_FIELD_CREATE_FORM_TABS = [
"general",
"organize",
] as const
export const PRODUCT_CUSTOM_FIELD_FORM_TABS = [
...PRODUCT_CUSTOM_FIELD_CREATE_FORM_TABS,
] as const
export const PRODUCT_CUSTOM_FIELD_DISPLAY_ZONES = [
"general",
"organize",
"attributes",
] as const
export const PRODUCT_CUSTOM_FIELD_LINK_PATHS = [
`${PRODUCT_CUSTOM_FIELD_MODEL}.$link`,
] as const
export const PRODUCT_CUSTOM_FIELD_FORM_CONFIG_PATHS = [
...PRODUCT_CUSTOM_FIELD_FORM_ZONES.map(
(form) => `${PRODUCT_CUSTOM_FIELD_MODEL}.${form}.$config`
),
] as const
export const PRODUCT_CUSTOM_FIELD_FORM_FIELD_PATHS = [
...PRODUCT_CUSTOM_FIELD_FORM_ZONES.flatMap((form) => {
return form === "create"
? PRODUCT_CUSTOM_FIELD_CREATE_FORM_TABS.map(
(tab) => `${PRODUCT_CUSTOM_FIELD_MODEL}.${form}.${tab}.$field`
)
: [`${PRODUCT_CUSTOM_FIELD_MODEL}.${form}.$field`]
}),
] as const
export const PRODUCT_CUSTOM_FIELD_DISPLAY_PATHS = [
...PRODUCT_CUSTOM_FIELD_DISPLAY_ZONES.map(
(id) => `${PRODUCT_CUSTOM_FIELD_MODEL}.${id}.$display`
),
] as const

View File

@@ -0,0 +1,10 @@
import {
PRODUCT_CUSTOM_FIELD_DISPLAY_ZONES,
PRODUCT_CUSTOM_FIELD_FORM_TABS,
PRODUCT_CUSTOM_FIELD_FORM_ZONES,
} from "./constants"
export type ProductFormZone = (typeof PRODUCT_CUSTOM_FIELD_FORM_ZONES)[number]
export type ProductFormTab = (typeof PRODUCT_CUSTOM_FIELD_FORM_TABS)[number]
export type ProductDisplayZone =
(typeof PRODUCT_CUSTOM_FIELD_DISPLAY_ZONES)[number]

View File

@@ -0,0 +1,48 @@
import {
CUSTOM_FIELD_CONTAINER_ZONES,
CUSTOM_FIELD_FORM_TABS,
CUSTOM_FIELD_FORM_ZONES,
CUSTOM_FIELD_MODELS,
} from "./constants"
import type {
ProductDisplayZone,
ProductFormTab,
ProductFormZone,
} from "./product"
export type CustomFieldModel = (typeof CUSTOM_FIELD_MODELS)[number]
export type CustomFieldFormZone = (typeof CUSTOM_FIELD_FORM_ZONES)[number]
export type CustomFieldFormTab = (typeof CUSTOM_FIELD_FORM_TABS)[number]
export type CustomFieldContainerZone =
(typeof CUSTOM_FIELD_CONTAINER_ZONES)[number]
export type CustomFieldZone = CustomFieldFormZone | CustomFieldContainerZone
export type CustomFieldImportType = "display" | "field" | "link" | "config"
export interface CustomFieldModelFormMap {
product: ProductFormZone
}
export interface CustomFieldModelContainerMap {
product: ProductDisplayZone
}
export type CustomFieldModelFormTabsMap = {
product: {
create: ProductFormTab
edit: never
organize: never
attributes: never
}
customer: {
create: never
edit: never
}
}
export type CustomFieldFormKeys<T extends CustomFieldModel> =
CustomFieldModelFormMap[T]

View File

@@ -0,0 +1,54 @@
import {
CUSTOM_FIELD_CONTAINER_ZONES,
CUSTOM_FIELD_DISPLAY_PATHS,
CUSTOM_FIELD_FORM_CONFIG_PATHS,
CUSTOM_FIELD_FORM_FIELD_PATHS,
CUSTOM_FIELD_FORM_TABS,
CUSTOM_FIELD_FORM_ZONES,
CUSTOM_FIELD_LINK_PATHS,
CUSTOM_FIELD_MODELS,
} from "./constants"
import {
CustomFieldContainerZone,
CustomFieldFormTab,
CustomFieldFormZone,
CustomFieldModel,
} from "./types"
// Validators for individual segments of the custom field extension system
export function isValidCustomFieldModel(id: any): id is CustomFieldModel {
return CUSTOM_FIELD_MODELS.includes(id)
}
export function isValidCustomFieldFormZone(id: any): id is CustomFieldFormZone {
return CUSTOM_FIELD_FORM_ZONES.includes(id)
}
export function isValidCustomFieldFormTab(id: any): id is CustomFieldFormTab {
return CUSTOM_FIELD_FORM_TABS.includes(id)
}
export function isValidCustomFieldDisplayZone(
id: any
): id is CustomFieldContainerZone {
return CUSTOM_FIELD_CONTAINER_ZONES.includes(id)
}
// Validators for full paths of custom field extensions
export function isValidCustomFieldDisplayPath(id: any): id is string {
return CUSTOM_FIELD_DISPLAY_PATHS.includes(id)
}
export function isValidCustomFieldFormConfigPath(id: any): id is string {
return CUSTOM_FIELD_FORM_CONFIG_PATHS.includes(id)
}
export function isValidCustomFieldFormFieldPath(id: any): id is string {
return CUSTOM_FIELD_FORM_FIELD_PATHS.includes(id)
}
export function isValidCustomFieldLinkPath(id: any): id is string {
return CUSTOM_FIELD_LINK_PATHS.includes(id)
}

View File

@@ -1 +0,0 @@
export const ROUTE_IMPORTS = ["routes/pages", "routes/links"] as const

View File

@@ -1,3 +0,0 @@
import { ROUTE_IMPORTS } from "./constants"
export type RouteImport = (typeof ROUTE_IMPORTS)[number]

View File

@@ -1,40 +0,0 @@
import { ROUTE_IMPORTS } from "../routes"
import { INJECTION_ZONES } from "../widgets"
import { getVirtualId, getWidgetImport, resolveVirtualId } from "./utils"
const VIRTUAL_WIDGET_MODULES = INJECTION_ZONES.map((zone) => {
return getVirtualId(getWidgetImport(zone))
})
const VIRTUAL_ROUTE_MODULES = ROUTE_IMPORTS.map((route) => {
return getVirtualId(route)
})
/**
* All virtual modules that are used in the admin panel. Virtual modules are used
* to inject custom widgets, routes and settings. A virtual module is imported using
* a string that corresponds to the id of the virtual module.
*
* @example
* ```ts
* import ProductDetailsBefore from "virtual:medusa/widgets/product/details/before"
* ```
*/
export const VIRTUAL_MODULES = [
...VIRTUAL_WIDGET_MODULES,
...VIRTUAL_ROUTE_MODULES,
]
/**
* Reolved paths to all virtual widget modules.
*/
export const RESOLVED_WIDGET_MODULES = VIRTUAL_WIDGET_MODULES.map((id) => {
return resolveVirtualId(id)
})
/**
* Reolved paths to all virtual route modules.
*/
export const RESOLVED_ROUTE_MODULES = VIRTUAL_ROUTE_MODULES.map((id) => {
return resolveVirtualId(id)
})

View File

@@ -1,2 +0,0 @@
export * from "./constants"
export * from "./utils"

View File

@@ -1,25 +0,0 @@
import { InjectionZone } from "../widgets"
const PREFIX = "virtual:medusa/"
export const getVirtualId = (name: string) => {
return `${PREFIX}${name}`
}
export const resolveVirtualId = (id: string) => {
return `\0${id}`
}
export const getWidgetImport = (zone: InjectionZone) => {
return `widgets/${zone.replace(/\./g, "/")}`
}
export const getWidgetZone = (resolvedId: string): InjectionZone => {
const virtualPrefix = `\0${PREFIX}widgets/`
const zone = resolvedId
.replace(virtualPrefix, "")
.replace(/\//g, ".") as InjectionZone
return zone as InjectionZone
}