) => {
+ if (isLoading) {
+ return (
+
+ )
+ }
+
+ const noQuery =
+ Object.values(queryObject).filter((v) => Boolean(v)).length === 0
+ const noResults = !isLoading && count === 0 && !noQuery
+ const noRecords = !isLoading && count === 0 && noQuery
+
+ if (noRecords) {
+ return
+ }
+
+ return (
+
+
+
+
+ )
+}
diff --git a/packages/admin-next/dashboard/src/components/table/data-table/hooks.tsx b/packages/admin-next/dashboard/src/components/table/data-table/hooks.tsx
new file mode 100644
index 0000000000000..aeda07245406c
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/data-table/hooks.tsx
@@ -0,0 +1,73 @@
+import { useSearchParams } from "react-router-dom"
+
+export const useSelectedParams = ({
+ param,
+ prefix,
+ multiple = false,
+}: {
+ param: string
+ prefix?: string
+ multiple?: boolean
+}) => {
+ const [searchParams, setSearchParams] = useSearchParams()
+ const identifier = prefix ? `${prefix}_${param}` : param
+ const offsetKey = prefix ? `${prefix}_offset` : "offset"
+
+ const add = (value: string) => {
+ setSearchParams((prev) => {
+ const newValue = new URLSearchParams(prev)
+
+ const updateMultipleValues = () => {
+ const existingValues = newValue.get(identifier)?.split(",") || []
+
+ if (!existingValues.includes(value)) {
+ existingValues.push(value)
+ newValue.set(identifier, existingValues.join(","))
+ }
+ }
+
+ const updateSingleValue = () => {
+ newValue.set(identifier, value)
+ }
+
+ multiple ? updateMultipleValues() : updateSingleValue()
+ newValue.delete(offsetKey)
+
+ return newValue
+ })
+ }
+
+ const deleteParam = (value?: string) => {
+ const deleteMultipleValues = (prev: URLSearchParams) => {
+ const existingValues = prev.get(identifier)?.split(",") || []
+ const index = existingValues.indexOf(value || "")
+ if (index > -1) {
+ existingValues.splice(index, 1)
+ prev.set(identifier, existingValues.join(","))
+ }
+ }
+
+ const deleteSingleValue = (prev: URLSearchParams) => {
+ prev.delete(identifier)
+ }
+
+ setSearchParams((prev) => {
+ if (value) {
+ multiple ? deleteMultipleValues(prev) : deleteSingleValue(prev)
+ if (!prev.get(identifier)) {
+ prev.delete(identifier)
+ }
+ } else {
+ prev.delete(identifier)
+ }
+ prev.delete(offsetKey)
+ return prev
+ })
+ }
+
+ const get = () => {
+ return searchParams.get(identifier)?.split(",").filter(Boolean) || []
+ }
+
+ return { add, delete: deleteParam, get }
+}
diff --git a/packages/admin-next/dashboard/src/components/table/data-table/index.ts b/packages/admin-next/dashboard/src/components/table/data-table/index.ts
new file mode 100644
index 0000000000000..78f00d949d53b
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/data-table/index.ts
@@ -0,0 +1,2 @@
+export * from "./data-table"
+export type { Filter } from "./data-table-filter"
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/common/date-cell/date-cell.tsx b/packages/admin-next/dashboard/src/components/table/table-cells/common/date-cell/date-cell.tsx
new file mode 100644
index 0000000000000..44dda62fb4653
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/common/date-cell/date-cell.tsx
@@ -0,0 +1,41 @@
+import { Tooltip } from "@medusajs/ui"
+import format from "date-fns/format"
+import { useTranslation } from "react-i18next"
+
+type DateCellProps = {
+ date: Date
+}
+
+export const DateCell = ({ date }: DateCellProps) => {
+ const value = new Date(date)
+ value.setMinutes(value.getMinutes() - value.getTimezoneOffset())
+
+ const hour12 = Intl.DateTimeFormat().resolvedOptions().hour12
+ const timestampFormat = hour12 ? "dd MMM yyyy hh:MM a" : "dd MMM yyyy HH:MM"
+
+ return (
+
+ {`${format(
+ value,
+ timestampFormat
+ )}`}
+ }
+ >
+ {format(value, "dd MMM yyyy")}
+
+
+ )
+}
+
+export const DateHeader = () => {
+ const { t } = useTranslation()
+
+ return (
+
+ {t("fields.date")}
+
+ )
+}
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/common/date-cell/index.ts b/packages/admin-next/dashboard/src/components/table/table-cells/common/date-cell/index.ts
new file mode 100644
index 0000000000000..9bf7e52ed0236
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/common/date-cell/index.ts
@@ -0,0 +1 @@
+export * from "./date-cell"
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/common/status-cell/index.ts b/packages/admin-next/dashboard/src/components/table/table-cells/common/status-cell/index.ts
new file mode 100644
index 0000000000000..8cc5d6026b4fb
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/common/status-cell/index.ts
@@ -0,0 +1 @@
+export * from "./status-cell"
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/common/status-cell/status-cell.tsx b/packages/admin-next/dashboard/src/components/table/table-cells/common/status-cell/status-cell.tsx
new file mode 100644
index 0000000000000..168a94117e69e
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/common/status-cell/status-cell.tsx
@@ -0,0 +1,32 @@
+import { clx } from "@medusajs/ui"
+import { PropsWithChildren } from "react"
+
+type StatusCellProps = PropsWithChildren<{
+ color?: "green" | "red" | "blue" | "orange" | "grey" | "purple"
+}>
+
+export const StatusCell = ({ color, children }: StatusCellProps) => {
+ return (
+
+ )
+}
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/customer-cell/customer-cell.tsx b/packages/admin-next/dashboard/src/components/table/table-cells/order/customer-cell/customer-cell.tsx
new file mode 100644
index 0000000000000..af558b959cec9
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/customer-cell/customer-cell.tsx
@@ -0,0 +1,29 @@
+import { Customer } from "@medusajs/medusa"
+import { useTranslation } from "react-i18next"
+
+export const CustomerCell = ({ customer }: { customer: Customer | null }) => {
+ if (!customer) {
+ return -
+ }
+
+ const { first_name, last_name, email } = customer
+ const name = [first_name, last_name].filter(Boolean).join(" ")
+
+ return (
+
+ )
+}
+
+export const CustomerHeader = () => {
+ const { t } = useTranslation()
+
+ return (
+
+ {t("fields.customer")}
+
+ )
+}
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/customer-cell/index.ts b/packages/admin-next/dashboard/src/components/table/table-cells/order/customer-cell/index.ts
new file mode 100644
index 0000000000000..dbdd97615af02
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/customer-cell/index.ts
@@ -0,0 +1 @@
+export * from "./customer-cell"
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/display-id-cell/display-id-cell.tsx b/packages/admin-next/dashboard/src/components/table/table-cells/order/display-id-cell/display-id-cell.tsx
new file mode 100644
index 0000000000000..e4f2e48aeb6ab
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/display-id-cell/display-id-cell.tsx
@@ -0,0 +1,19 @@
+import { useTranslation } from "react-i18next"
+
+export const DisplayIdCell = ({ displayId }: { displayId: number }) => {
+ return (
+
+ #{displayId}
+
+ )
+}
+
+export const DisplayIdHeader = () => {
+ const { t } = useTranslation()
+
+ return (
+
+ {t("fields.order")}
+
+ )
+}
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/display-id-cell/index.ts b/packages/admin-next/dashboard/src/components/table/table-cells/order/display-id-cell/index.ts
new file mode 100644
index 0000000000000..057f15de5bdcb
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/display-id-cell/index.ts
@@ -0,0 +1 @@
+export * from "./display-id-cell"
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/fulfillment-status-cell/fulfillment-status-cell.tsx b/packages/admin-next/dashboard/src/components/table/table-cells/order/fulfillment-status-cell/fulfillment-status-cell.tsx
new file mode 100644
index 0000000000000..d899e85468a31
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/fulfillment-status-cell/fulfillment-status-cell.tsx
@@ -0,0 +1,46 @@
+import type { FulfillmentStatus } from "@medusajs/medusa"
+import { useTranslation } from "react-i18next"
+import { StatusCell } from "../../common/status-cell"
+
+type FulfillmentStatusCellProps = {
+ status: FulfillmentStatus
+}
+
+export const FulfillmentStatusCell = ({
+ status,
+}: FulfillmentStatusCellProps) => {
+ const { t } = useTranslation()
+
+ const [label, color] = {
+ not_fulfilled: [t("orders.fulfillmentStatus.notFulfilled"), "red"],
+ partially_fulfilled: [
+ t("orders.fulfillmentStatus.partiallyFulfilled"),
+ "orange",
+ ],
+ fulfilled: [t("orders.fulfillmentStatus.fulfilled"), "green"],
+ partially_shipped: [
+ t("orders.fulfillmentStatus.partiallyShipped"),
+ "orange",
+ ],
+ shipped: [t("orders.fulfillmentStatus.shipped"), "green"],
+ partially_returned: [
+ t("orders.fulfillmentStatus.partiallyReturned"),
+ "orange",
+ ],
+ returned: [t("orders.fulfillmentStatus.returned"), "green"],
+ canceled: [t("orders.fulfillmentStatus.canceled"), "red"],
+ requires_action: [t("orders.fulfillmentStatus.requresAction"), "orange"],
+ }[status] as [string, "red" | "orange" | "green"]
+
+ return {label}
+}
+
+export const FulfillmentStatusHeader = () => {
+ const { t } = useTranslation()
+
+ return (
+
+ {t("fields.fulfillment")}
+
+ )
+}
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/fulfillment-status-cell/index.ts b/packages/admin-next/dashboard/src/components/table/table-cells/order/fulfillment-status-cell/index.ts
new file mode 100644
index 0000000000000..a0f92c11b9f99
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/fulfillment-status-cell/index.ts
@@ -0,0 +1 @@
+export * from "./fulfillment-status-cell"
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/items-cell/index.ts b/packages/admin-next/dashboard/src/components/table/table-cells/order/items-cell/index.ts
new file mode 100644
index 0000000000000..8df6791eaee23
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/items-cell/index.ts
@@ -0,0 +1 @@
+export * from "./items-cell"
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/items-cell/items-cell.tsx b/packages/admin-next/dashboard/src/components/table/table-cells/order/items-cell/items-cell.tsx
new file mode 100644
index 0000000000000..fc0c3b3403005
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/items-cell/items-cell.tsx
@@ -0,0 +1,26 @@
+import type { LineItem } from "@medusajs/medusa"
+import { useTranslation } from "react-i18next"
+
+export const ItemsCell = ({ items }: { items: LineItem[] }) => {
+ const { t } = useTranslation()
+
+ return (
+
+
+ {t("general.items", {
+ count: items.length,
+ })}
+
+
+ )
+}
+
+export const ItemsHeader = () => {
+ const { t } = useTranslation()
+
+ return (
+
+ {t("fields.items")}
+
+ )
+}
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/payment-status-cell/index.ts b/packages/admin-next/dashboard/src/components/table/table-cells/order/payment-status-cell/index.ts
new file mode 100644
index 0000000000000..f6c4b069ee991
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/payment-status-cell/index.ts
@@ -0,0 +1 @@
+export * from "./payment-status-cell"
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/payment-status-cell/payment-status-cell.tsx b/packages/admin-next/dashboard/src/components/table/table-cells/order/payment-status-cell/payment-status-cell.tsx
new file mode 100644
index 0000000000000..db8828fa26799
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/payment-status-cell/payment-status-cell.tsx
@@ -0,0 +1,33 @@
+import type { PaymentStatus } from "@medusajs/medusa"
+import { useTranslation } from "react-i18next"
+import { StatusCell } from "../../common/status-cell"
+
+type PaymentStatusCellProps = {
+ status: PaymentStatus
+}
+
+export const PaymentStatusCell = ({ status }: PaymentStatusCellProps) => {
+ const { t } = useTranslation()
+
+ const [label, color] = {
+ not_paid: [t("orders.paymentStatus.notPaid"), "red"],
+ awaiting: [t("orders.paymentStatus.awaiting"), "orange"],
+ captured: [t("orders.paymentStatus.captured"), "green"],
+ refunded: [t("orders.paymentStatus.refunded"), "green"],
+ partially_refunded: [t("orders.paymentStatus.partiallyRefunded"), "orange"],
+ canceled: [t("orders.paymentStatus.canceled"), "red"],
+ requires_action: [t("orders.paymentStatus.requresAction"), "orange"],
+ }[status] as [string, "red" | "orange" | "green"]
+
+ return {label}
+}
+
+export const PaymentStatusHeader = () => {
+ const { t } = useTranslation()
+
+ return (
+
+ {t("fields.payment")}
+
+ )
+}
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/sales-channel-cell/index.ts b/packages/admin-next/dashboard/src/components/table/table-cells/order/sales-channel-cell/index.ts
new file mode 100644
index 0000000000000..8040cf7b1b40e
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/sales-channel-cell/index.ts
@@ -0,0 +1 @@
+export * from "./sales-channel-cell"
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/sales-channel-cell/sales-channel-cell.tsx b/packages/admin-next/dashboard/src/components/table/table-cells/order/sales-channel-cell/sales-channel-cell.tsx
new file mode 100644
index 0000000000000..17e249d0418eb
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/sales-channel-cell/sales-channel-cell.tsx
@@ -0,0 +1,30 @@
+import { SalesChannel } from "@medusajs/medusa"
+import { useTranslation } from "react-i18next"
+
+export const SalesChannelCell = ({
+ channel,
+}: {
+ channel: SalesChannel | null
+}) => {
+ if (!channel) {
+ return -
+ }
+
+ const { name } = channel
+
+ return (
+
+ {name}
+
+ )
+}
+
+export const SalesChannelHeader = () => {
+ const { t } = useTranslation()
+
+ return (
+
+ {t("fields.salesChannel")}
+
+ )
+}
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/total-cell/index.ts b/packages/admin-next/dashboard/src/components/table/table-cells/order/total-cell/index.ts
new file mode 100644
index 0000000000000..a58e61c257cee
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/total-cell/index.ts
@@ -0,0 +1 @@
+export * from "./total-cell"
diff --git a/packages/admin-next/dashboard/src/components/table/table-cells/order/total-cell/total-cell.tsx b/packages/admin-next/dashboard/src/components/table/table-cells/order/total-cell/total-cell.tsx
new file mode 100644
index 0000000000000..58646ee9339f4
--- /dev/null
+++ b/packages/admin-next/dashboard/src/components/table/table-cells/order/total-cell/total-cell.tsx
@@ -0,0 +1,44 @@
+import { useTranslation } from "react-i18next"
+import { getPresentationalAmount } from "../../../../../lib/money-amount-helpers"
+
+type TotalCellProps = {
+ currencyCode: string
+ total: number | null
+}
+
+export const TotalCell = ({ currencyCode, total }: TotalCellProps) => {
+ if (!total) {
+ return -
+ }
+
+ const formatted = new Intl.NumberFormat(undefined, {
+ style: "currency",
+ currency: currencyCode,
+ currencyDisplay: "narrowSymbol",
+ }).format(0)
+
+ const symbol = formatted.replace(/\d/g, "").replace(/[.,]/g, "").trim()
+
+ const presentationAmount = getPresentationalAmount(total, currencyCode)
+ const formattedTotal = new Intl.NumberFormat(undefined, {
+ style: "decimal",
+ }).format(presentationAmount)
+
+ return (
+
+
+ {symbol} {formattedTotal} {currencyCode.toUpperCase()}
+
+
+ )
+}
+
+export const TotalHeader = () => {
+ const { t } = useTranslation()
+
+ return (
+
+ {t("fields.total")}
+
+ )
+}
diff --git a/packages/admin-next/dashboard/src/hooks/table/columns/use-order-table-columns.tsx b/packages/admin-next/dashboard/src/hooks/table/columns/use-order-table-columns.tsx
new file mode 100644
index 0000000000000..490db287b1497
--- /dev/null
+++ b/packages/admin-next/dashboard/src/hooks/table/columns/use-order-table-columns.tsx
@@ -0,0 +1,133 @@
+import { Order } from "@medusajs/medusa"
+import {
+ ColumnDef,
+ ColumnDefBase,
+ createColumnHelper,
+} from "@tanstack/react-table"
+import { useMemo } from "react"
+import {
+ DateCell,
+ DateHeader,
+} from "../../../components/table/table-cells/common/date-cell"
+import {
+ DisplayIdCell,
+ DisplayIdHeader,
+} from "../../../components/table/table-cells/order/display-id-cell"
+import {
+ FulfillmentStatusCell,
+ FulfillmentStatusHeader,
+} from "../../../components/table/table-cells/order/fulfillment-status-cell"
+import {
+ ItemsCell,
+ ItemsHeader,
+} from "../../../components/table/table-cells/order/items-cell"
+import {
+ PaymentStatusCell,
+ PaymentStatusHeader,
+} from "../../../components/table/table-cells/order/payment-status-cell"
+import {
+ SalesChannelCell,
+ SalesChannelHeader,
+} from "../../../components/table/table-cells/order/sales-channel-cell"
+import {
+ TotalCell,
+ TotalHeader,
+} from "../../../components/table/table-cells/order/total-cell"
+
+// We have to use any here, as the type of Order is so complex that it lags the TS server
+const columnHelper = createColumnHelper()
+
+type UseOrderTableColumnsProps = {
+ exclude?: string[]
+}
+
+export const useOrderTableColumns = (props: UseOrderTableColumnsProps) => {
+ const { exclude = [] } = props ?? {}
+
+ const columns = useMemo(
+ () => [
+ columnHelper.accessor("display_id", {
+ header: () => ,
+ cell: ({ getValue }) => {
+ const id = getValue()
+
+ return
+ },
+ }),
+ columnHelper.accessor("created_at", {
+ header: () => ,
+ cell: ({ getValue }) => {
+ const date = new Date(getValue())
+
+ return
+ },
+ }),
+ columnHelper.accessor("sales_channel", {
+ header: () => ,
+ cell: ({ getValue }) => {
+ const channel = getValue()
+
+ return
+ },
+ }),
+ columnHelper.accessor("payment_status", {
+ header: () => ,
+ cell: ({ getValue }) => {
+ const status = getValue()
+
+ return
+ },
+ }),
+ columnHelper.accessor("fulfillment_status", {
+ header: () => ,
+ cell: ({ getValue }) => {
+ const status = getValue()
+
+ return
+ },
+ }),
+ columnHelper.accessor("items", {
+ header: () => ,
+ cell: ({ getValue }) => {
+ const items = getValue()
+
+ return
+ },
+ }),
+ columnHelper.accessor("total", {
+ header: () => ,
+ cell: ({ getValue, row }) => {
+ const total = getValue()
+ const currencyCode = row.original.currency_code
+
+ return
+ },
+ }),
+ ],
+ []
+ )
+
+ const isAccessorColumnDef = (
+ c: any
+ ): c is ColumnDef & { accessorKey: string } => {
+ return c.accessorKey !== undefined
+ }
+
+ const isDisplayColumnDef = (
+ c: any
+ ): c is ColumnDef & { id: string } => {
+ return c.id !== undefined
+ }
+
+ const shouldExclude = >(c: TDef) => {
+ if (isAccessorColumnDef(c)) {
+ return exclude.includes(c.accessorKey)
+ } else if (isDisplayColumnDef(c)) {
+ return exclude.includes(c.id)
+ }
+
+ return false
+ }
+
+ return columns.filter((c) => !shouldExclude(c)) as ColumnDef[]
+}
diff --git a/packages/admin-next/dashboard/src/hooks/table/filters/use-order-table-filters.tsx b/packages/admin-next/dashboard/src/hooks/table/filters/use-order-table-filters.tsx
new file mode 100644
index 0000000000000..aa5b309f05684
--- /dev/null
+++ b/packages/admin-next/dashboard/src/hooks/table/filters/use-order-table-filters.tsx
@@ -0,0 +1,154 @@
+import { useAdminRegions, useAdminSalesChannels } from "medusa-react"
+import { useTranslation } from "react-i18next"
+
+import type { Filter } from "../../../components/table/data-table"
+
+export const useOrderTableFilters = (): Filter[] => {
+ const { t } = useTranslation()
+
+ const { regions } = useAdminRegions({
+ limit: 1000,
+ fields: "id,name",
+ expand: "",
+ })
+
+ const { sales_channels } = useAdminSalesChannels({
+ limit: 1000,
+ fields: "id,name",
+ expand: "",
+ })
+
+ let filters: Filter[] = []
+
+ if (regions) {
+ const regionFilter: Filter = {
+ key: "region_id",
+ label: t("fields.region"),
+ type: "select",
+ options: regions.map((r) => ({
+ label: r.name,
+ value: r.id,
+ })),
+ multiple: true,
+ searchable: true,
+ }
+
+ filters = [...filters, regionFilter]
+ }
+
+ if (sales_channels) {
+ const salesChannelFilter: Filter = {
+ key: "sales_channel_id",
+ label: t("fields.salesChannel"),
+ type: "select",
+ multiple: true,
+ searchable: true,
+ options: sales_channels.map((s) => ({
+ label: s.name,
+ value: s.id,
+ })),
+ }
+
+ filters = [...filters, salesChannelFilter]
+ }
+
+ const paymentStatusFilter: Filter = {
+ key: "payment_status",
+ label: t("orders.paymentStatusLabel"),
+ type: "select",
+ multiple: true,
+ options: [
+ {
+ label: t("orders.paymentStatus.notPaid"),
+ value: "not_paid",
+ },
+ {
+ label: t("orders.paymentStatus.awaiting"),
+ value: "awaiting",
+ },
+ {
+ label: t("orders.paymentStatus.captured"),
+ value: "captured",
+ },
+ {
+ label: t("orders.paymentStatus.refunded"),
+ value: "refunded",
+ },
+ {
+ label: t("orders.paymentStatus.partiallyRefunded"),
+ value: "partially_refunded",
+ },
+ {
+ label: t("orders.paymentStatus.canceled"),
+ value: "canceled",
+ },
+ {
+ label: t("orders.paymentStatus.requresAction"),
+ value: "requires_action",
+ },
+ ],
+ }
+
+ const fulfillmentStatusFilter: Filter = {
+ key: "fulfillment_status",
+ label: t("orders.fulfillmentStatusLabel"),
+ type: "select",
+ multiple: true,
+ options: [
+ {
+ label: t("orders.fulfillmentStatus.notFulfilled"),
+ value: "not_fulfilled",
+ },
+ {
+ label: t("orders.fulfillmentStatus.fulfilled"),
+ value: "fulfilled",
+ },
+ {
+ label: t("orders.fulfillmentStatus.partiallyFulfilled"),
+ value: "partially_fulfilled",
+ },
+ {
+ label: t("orders.fulfillmentStatus.returned"),
+ value: "returned",
+ },
+ {
+ label: t("orders.fulfillmentStatus.partiallyReturned"),
+ value: "partially_returned",
+ },
+ {
+ label: t("orders.fulfillmentStatus.shipped"),
+ value: "shipped",
+ },
+ {
+ label: t("orders.fulfillmentStatus.partiallyShipped"),
+ value: "partially_shipped",
+ },
+ {
+ label: t("orders.fulfillmentStatus.canceled"),
+ value: "canceled",
+ },
+ {
+ label: t("orders.fulfillmentStatus.requresAction"),
+ value: "requires_action",
+ },
+ ],
+ }
+
+ const dateFilters: Filter[] = [
+ { label: "Created At", key: "created_at" },
+ { label: "Updated At", key: "updated_at" },
+ ].map((f) => ({
+ key: f.key,
+ label: f.label,
+ type: "date",
+ }))
+
+ filters = [
+ ...filters,
+ paymentStatusFilter,
+ fulfillmentStatusFilter,
+ ...dateFilters,
+ ]
+
+ return filters
+}
diff --git a/packages/admin-next/dashboard/src/hooks/table/query/use-order-table-query.tsx b/packages/admin-next/dashboard/src/hooks/table/query/use-order-table-query.tsx
new file mode 100644
index 0000000000000..bcf52dad14c1d
--- /dev/null
+++ b/packages/admin-next/dashboard/src/hooks/table/query/use-order-table-query.tsx
@@ -0,0 +1,58 @@
+import { AdminGetOrdersParams } from "@medusajs/medusa"
+import { useQueryParams } from "../../use-query-params"
+
+type UseOrderTableQueryProps = {
+ prefix?: string
+ pageSize?: number
+}
+
+/**
+ * TODO: Enable `order` query param when staging is updated
+ */
+
+export const useOrderTableQuery = ({
+ prefix,
+ pageSize = 50,
+}: UseOrderTableQueryProps) => {
+ const queryObject = useQueryParams(
+ [
+ "offset",
+ "q",
+ "created_at",
+ "updated_at",
+ "region_id",
+ "sales_channel_id",
+ "payment_status",
+ "fulfillment_status",
+ ],
+ prefix
+ )
+
+ const {
+ offset,
+ sales_channel_id,
+ created_at,
+ updated_at,
+ fulfillment_status,
+ payment_status,
+ region_id,
+ q,
+ } = queryObject
+
+ const searchParams: AdminGetOrdersParams = {
+ limit: pageSize,
+ offset: offset ? Number(offset) : 0,
+ sales_channel_id: sales_channel_id?.split(","),
+ fulfillment_status: fulfillment_status?.split(","),
+ payment_status: payment_status?.split(","),
+ created_at: created_at ? JSON.parse(created_at) : undefined,
+ updated_at: updated_at ? JSON.parse(updated_at) : undefined,
+ region_id: region_id?.split(","),
+ q,
+ }
+
+ return {
+ searchParams,
+ raw: queryObject,
+ }
+}
diff --git a/packages/admin-next/dashboard/src/hooks/use-data-table.tsx b/packages/admin-next/dashboard/src/hooks/use-data-table.tsx
new file mode 100644
index 0000000000000..5be85018f4e4c
--- /dev/null
+++ b/packages/admin-next/dashboard/src/hooks/use-data-table.tsx
@@ -0,0 +1,112 @@
+import {
+ ColumnDef,
+ OnChangeFn,
+ PaginationState,
+ Row,
+ getCoreRowModel,
+ getPaginationRowModel,
+ useReactTable,
+} from "@tanstack/react-table"
+import { useEffect, useMemo, useState } from "react"
+import { useSearchParams } from "react-router-dom"
+
+type UseDataTableProps = {
+ data?: TData[]
+ columns: ColumnDef[]
+ count?: number
+ pageSize?: number
+ enableRowSelection?: boolean | ((row: Row) => boolean)
+ enablePagination?: boolean
+ getRowId?: (original: TData, index: number) => string
+ prefix?: string
+}
+
+export const useDataTable = ({
+ data = [],
+ columns,
+ count = 0,
+ pageSize: _pageSize = 50,
+ enablePagination = true,
+ enableRowSelection = false,
+ getRowId,
+ prefix,
+}: UseDataTableProps) => {
+ const [searchParams, setSearchParams] = useSearchParams()
+ const offsetKey = `${prefix ? `${prefix}_` : ""}offset`
+ const offset = searchParams.get(offsetKey)
+
+ const [{ pageIndex, pageSize }, setPagination] = useState({
+ pageIndex: offset ? Math.ceil(Number(offset) / _pageSize) : 0,
+ pageSize: _pageSize,
+ })
+ const pagination = useMemo(
+ () => ({
+ pageIndex,
+ pageSize,
+ }),
+ [pageIndex, pageSize]
+ )
+ const [rowSelection, setRowSelection] = useState({})
+
+ useEffect(() => {
+ if (!enablePagination) {
+ return
+ }
+
+ const index = offset ? Math.ceil(Number(offset) / _pageSize) : 0
+
+ if (index === pageIndex) {
+ return
+ }
+
+ setPagination((prev) => ({
+ ...prev,
+ pageIndex: index,
+ }))
+ }, [offset, enablePagination, _pageSize, pageIndex])
+
+ const onPaginationChange = (
+ updater: (old: PaginationState) => PaginationState
+ ) => {
+ const state = updater(pagination)
+ const { pageIndex, pageSize } = state
+
+ setSearchParams((prev) => {
+ if (!pageIndex) {
+ prev.delete(offsetKey)
+ return prev
+ }
+
+ const newSearch = new URLSearchParams(prev)
+ newSearch.set(offsetKey, String(pageIndex * pageSize))
+
+ return newSearch
+ })
+
+ setPagination(state)
+ return state
+ }
+
+ const table = useReactTable({
+ data,
+ columns,
+ state: {
+ rowSelection,
+ pagination: enablePagination ? pagination : undefined,
+ },
+ pageCount: Math.ceil((count ?? 0) / pageSize),
+ enableRowSelection,
+ getRowId,
+ onRowSelectionChange: enableRowSelection ? setRowSelection : undefined,
+ onPaginationChange: enablePagination
+ ? (onPaginationChange as OnChangeFn)
+ : undefined,
+ getCoreRowModel: getCoreRowModel(),
+ getPaginationRowModel: enablePagination
+ ? getPaginationRowModel()
+ : undefined,
+ manualPagination: enablePagination ? true : undefined,
+ })
+
+ return { table }
+}
diff --git a/packages/admin-next/dashboard/src/hooks/use-query-params.tsx b/packages/admin-next/dashboard/src/hooks/use-query-params.tsx
index afb282362e58b..623975e5fb362 100644
--- a/packages/admin-next/dashboard/src/hooks/use-query-params.tsx
+++ b/packages/admin-next/dashboard/src/hooks/use-query-params.tsx
@@ -1,15 +1,23 @@
import { useSearchParams } from "react-router-dom"
+type QueryParams = {
+ [key in T]: string | undefined
+}
+
export function useQueryParams(
- keys: T[]
-): Record {
+ keys: T[],
+ prefix?: string
+): QueryParams {
const [params] = useSearchParams()
// Use a type assertion to initialize the result
- const result = {} as Record
+ const result = {} as QueryParams
keys.forEach((key) => {
- result[key] = params.get(key) || undefined
+ const prefixedKey = prefix ? `${prefix}_${key}` : key
+ const value = params.get(prefixedKey) || undefined
+
+ result[key] = value
})
return result
diff --git a/packages/admin-next/dashboard/src/providers/router-provider/router-provider.tsx b/packages/admin-next/dashboard/src/providers/router-provider/router-provider.tsx
index dbdb2d99dda0b..3cb8603b76591 100644
--- a/packages/admin-next/dashboard/src/providers/router-provider/router-provider.tsx
+++ b/packages/admin-next/dashboard/src/providers/router-provider/router-provider.tsx
@@ -74,7 +74,7 @@ const router = createBrowserRouter([
children: [
{
index: true,
- lazy: () => import("../../routes/orders/list"),
+ lazy: () => import("../../routes/orders/order-list"),
},
{
path: ":id",
diff --git a/packages/admin-next/dashboard/src/routes/customers/customer-detail/components/customer-order-section/customer-order-section.tsx b/packages/admin-next/dashboard/src/routes/customers/customer-detail/components/customer-order-section/customer-order-section.tsx
index 026ad1f84db3c..a2f307c56867b 100644
--- a/packages/admin-next/dashboard/src/routes/customers/customer-detail/components/customer-order-section/customer-order-section.tsx
+++ b/packages/admin-next/dashboard/src/routes/customers/customer-detail/components/customer-order-section/customer-order-section.tsx
@@ -1,99 +1,62 @@
-import { ReceiptPercent } from "@medusajs/icons"
-import { Customer, Order } from "@medusajs/medusa"
-import { Button, Container, Heading, Table, clx } from "@medusajs/ui"
-import {
- PaginationState,
- RowSelectionState,
- createColumnHelper,
- flexRender,
- getCoreRowModel,
- useReactTable,
-} from "@tanstack/react-table"
+import { Customer } from "@medusajs/medusa"
+import { Button, Container, Heading } from "@medusajs/ui"
import { useAdminOrders } from "medusa-react"
-import { useMemo, useState } from "react"
import { useTranslation } from "react-i18next"
-import { useNavigate } from "react-router-dom"
-import { ActionMenu } from "../../../../../components/common/action-menu"
-import { NoRecords } from "../../../../../components/common/empty-table-content"
-import {
- OrderDateCell,
- OrderDisplayIdCell,
- OrderFulfillmentStatusCell,
- OrderPaymentStatusCell,
- OrderTotalCell,
-} from "../../../../../components/common/order-table-cells"
-import { Query } from "../../../../../components/filtering/query"
-import { LocalizedTablePagination } from "../../../../../components/localization/localized-table-pagination"
-import { useQueryParams } from "../../../../../hooks/use-query-params"
+import { DataTable } from "../../../../../components/table/data-table"
+import { useOrderTableColumns } from "../../../../../hooks/table/columns/use-order-table-columns"
+import { useOrderTableFilters } from "../../../../../hooks/table/filters/use-order-table-filters"
+import { useOrderTableQuery } from "../../../../../hooks/table/query/use-order-table-query"
+import { useDataTable } from "../../../../../hooks/use-data-table"
type CustomerGeneralSectionProps = {
customer: Customer
}
const PAGE_SIZE = 10
+const DEFAULT_RELATIONS = "customer,items,sales_channel"
+const DEFAULT_FIELDS =
+ "id,status,display_id,created_at,email,fulfillment_status,payment_status,total,currency_code"
export const CustomerOrderSection = ({
customer,
}: CustomerGeneralSectionProps) => {
const { t } = useTranslation()
- const navigate = useNavigate()
- const [{ pageIndex, pageSize }, setPagination] = useState({
- pageIndex: 0,
+ const { searchParams, raw } = useOrderTableQuery({
pageSize: PAGE_SIZE,
})
-
- const pagination = useMemo(
- () => ({
- pageIndex,
- pageSize,
- }),
- [pageIndex, pageSize]
- )
-
- const [rowSelection, setRowSelection] = useState({})
-
- const params = useQueryParams(["q"])
const { orders, count, isLoading, isError, error } = useAdminOrders(
{
customer_id: customer.id,
- limit: PAGE_SIZE,
- offset: pageIndex * PAGE_SIZE,
- fields:
- "id,status,display_id,created_at,email,fulfillment_status,payment_status,total,currency_code",
- ...params,
+ expand: DEFAULT_RELATIONS,
+ fields: DEFAULT_FIELDS,
+ ...searchParams,
},
{
keepPreviousData: true,
}
)
- const columns = useColumns()
+ const columns = useOrderTableColumns({
+ exclude: ["customer"],
+ })
+ const filters = useOrderTableFilters()
- const table = useReactTable({
+ const { table } = useDataTable({
data: orders ?? [],
columns,
- pageCount: Math.ceil((count ?? 0) / PAGE_SIZE),
- state: {
- pagination,
- rowSelection,
- },
- onPaginationChange: setPagination,
- onRowSelectionChange: setRowSelection,
- getCoreRowModel: getCoreRowModel(),
- manualPagination: true,
+ enablePagination: true,
+ count,
+ pageSize: PAGE_SIZE,
})
- const noRecords =
- Object.values(params).every((v) => !v) && !isLoading && !orders?.length
-
if (isError) {
throw error
}
return (
-
-
+
+
{t("orders.domain")}
- {!noRecords && (
-
- )}
- {noRecords ? (
-
- ) : (
-
-
-
- {table.getHeaderGroups().map((headerGroup) => {
- return (
-
- {headerGroup.headers.map((header) => {
- return (
-
- {flexRender(
- header.column.columnDef.header,
- header.getContext()
- )}
-
- )
- })}
-
- )
- })}
-
-
- {table.getRowModel().rows.map((row) => (
- navigate(`/orders/${row.original.id}`)}
- >
- {row.getVisibleCells().map((cell) => (
-
- {flexRender(
- cell.column.columnDef.cell,
- cell.getContext()
- )}
-
- ))}
-
- ))}
-
-
-
-
- )}
+ `/orders/${row.original.id}`}
+ filters={filters}
+ count={count}
+ isLoading={isLoading}
+ rowCount={PAGE_SIZE}
+ orderBy={["display_id", "created_at", "updated_at"]}
+ search={true}
+ queryObject={raw}
+ />
)
}
-
-const OrderActions = ({ order }: { order: Order }) => {
- const { t } = useTranslation()
-
- return (
-
,
- label: t("customers.viewOrder"),
- to: `/orders/${order.id}/edit`,
- },
- ],
- },
- ]}
- />
- )
-}
-
-const columnHelper = createColumnHelper
()
-
-const useColumns = () => {
- const { t } = useTranslation()
-
- return useMemo(
- () => [
- columnHelper.accessor("display_id", {
- header: "Order",
- cell: ({ getValue }) => ,
- }),
- columnHelper.accessor("created_at", {
- header: "Date",
- cell: ({ getValue }) => ,
- }),
- columnHelper.accessor("fulfillment_status", {
- header: "Fulfillment Status",
- cell: ({ getValue }) => (
-
- ),
- }),
- columnHelper.accessor("payment_status", {
- header: "Payment Status",
- cell: ({ getValue }) => ,
- }),
- columnHelper.accessor("total", {
- header: () => t("fields.total"),
- cell: ({ getValue, row }) => (
-
- ),
- }),
- columnHelper.display({
- id: "actions",
- cell: ({ row }) => ,
- }),
- ],
- [t]
- )
-}
diff --git a/packages/admin-next/dashboard/src/routes/orders/list/index.ts b/packages/admin-next/dashboard/src/routes/orders/list/index.ts
deleted file mode 100644
index ad7ea56183413..0000000000000
--- a/packages/admin-next/dashboard/src/routes/orders/list/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { OrderList as Component } from "./list";
diff --git a/packages/admin-next/dashboard/src/routes/orders/list/list.tsx b/packages/admin-next/dashboard/src/routes/orders/list/list.tsx
deleted file mode 100644
index d5498116ac06c..0000000000000
--- a/packages/admin-next/dashboard/src/routes/orders/list/list.tsx
+++ /dev/null
@@ -1,11 +0,0 @@
-import { Container, Heading } from "@medusajs/ui";
-
-export const OrderList = () => {
- return (
-
-
- Orders
-
-
- );
-};
diff --git a/packages/admin-next/dashboard/src/routes/orders/order-list/components/order-list-table/index.ts b/packages/admin-next/dashboard/src/routes/orders/order-list/components/order-list-table/index.ts
new file mode 100644
index 0000000000000..f6520707347f2
--- /dev/null
+++ b/packages/admin-next/dashboard/src/routes/orders/order-list/components/order-list-table/index.ts
@@ -0,0 +1 @@
+export * from "./order-list-table"
diff --git a/packages/admin-next/dashboard/src/routes/orders/order-list/components/order-list-table/order-list-table.tsx b/packages/admin-next/dashboard/src/routes/orders/order-list/components/order-list-table/order-list-table.tsx
new file mode 100644
index 0000000000000..05ba27416a2b2
--- /dev/null
+++ b/packages/admin-next/dashboard/src/routes/orders/order-list/components/order-list-table/order-list-table.tsx
@@ -0,0 +1,67 @@
+import { Container, Heading } from "@medusajs/ui"
+import { useAdminOrders } from "medusa-react"
+import { useTranslation } from "react-i18next"
+import { DataTable } from "../../../../../components/table/data-table/data-table"
+import { useOrderTableColumns } from "../../../../../hooks/table/columns/use-order-table-columns"
+import { useOrderTableFilters } from "../../../../../hooks/table/filters/use-order-table-filters"
+import { useOrderTableQuery } from "../../../../../hooks/table/query/use-order-table-query"
+import { useDataTable } from "../../../../../hooks/use-data-table"
+
+const PAGE_SIZE = 50
+const DEFAULT_RELATIONS = "customer,items,sales_channel"
+const DEFAULT_FIELDS =
+ "id,status,display_id,created_at,email,fulfillment_status,payment_status,total,currency_code"
+
+export const OrderListTable = () => {
+ const { t } = useTranslation()
+ const { searchParams, raw } = useOrderTableQuery({
+ pageSize: PAGE_SIZE,
+ })
+
+ const { orders, count, isError, error, isLoading } = useAdminOrders(
+ {
+ expand: DEFAULT_RELATIONS,
+ fields: DEFAULT_FIELDS,
+ ...searchParams,
+ },
+ {
+ keepPreviousData: true,
+ }
+ )
+
+ const filters = useOrderTableFilters()
+ const columns = useOrderTableColumns({})
+
+ const { table } = useDataTable({
+ data: orders ?? [],
+ columns,
+ enablePagination: true,
+ count,
+ pageSize: PAGE_SIZE,
+ })
+
+ if (isError) {
+ throw error
+ }
+
+ return (
+
+
+ {t("orders.domain")}
+
+ `/orders/${row.original.id}`}
+ filters={filters}
+ count={count}
+ search
+ isLoading={isLoading}
+ rowCount={PAGE_SIZE}
+ orderBy={["display_id", "created_at", "updated_at"]}
+ queryObject={raw}
+ />
+
+ )
+}
diff --git a/packages/admin-next/dashboard/src/routes/orders/order-list/index.ts b/packages/admin-next/dashboard/src/routes/orders/order-list/index.ts
new file mode 100644
index 0000000000000..0d3535fb846c6
--- /dev/null
+++ b/packages/admin-next/dashboard/src/routes/orders/order-list/index.ts
@@ -0,0 +1 @@
+export { OrderList as Component } from "./order-list"
diff --git a/packages/admin-next/dashboard/src/routes/orders/order-list/order-list.tsx b/packages/admin-next/dashboard/src/routes/orders/order-list/order-list.tsx
new file mode 100644
index 0000000000000..587cb88bf516d
--- /dev/null
+++ b/packages/admin-next/dashboard/src/routes/orders/order-list/order-list.tsx
@@ -0,0 +1,9 @@
+import { OrderListTable } from "./components/order-list-table"
+
+export const OrderList = () => {
+ return (
+
+
+
+ )
+}
diff --git a/packages/auth/integration-tests/__fixtures__/auth-user/index.ts b/packages/auth/integration-tests/__fixtures__/auth-user/index.ts
index 46e745ffdc18b..fefbdc9a6d90c 100644
--- a/packages/auth/integration-tests/__fixtures__/auth-user/index.ts
+++ b/packages/auth/integration-tests/__fixtures__/auth-user/index.ts
@@ -1,5 +1,5 @@
-import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AuthUser } from "@models"
+import { SqlEntityManager } from "@mikro-orm/postgresql"
export async function createAuthUsers(
manager: SqlEntityManager,
@@ -8,15 +8,18 @@ export async function createAuthUsers(
id: "test-id",
entity_id: "test-id",
provider: "manual",
+ scope: "store",
},
{
id: "test-id-1",
entity_id: "test-id-1",
provider: "manual",
+ scope: "store",
},
{
entity_id: "test-id-2",
provider: "store",
+ scope: "store",
},
]
): Promise {
diff --git a/packages/auth/integration-tests/__tests__/services/auth-provider/index.spec.ts b/packages/auth/integration-tests/__tests__/services/auth-provider/index.spec.ts
index 934bf94ec7d68..3ce97ecd458e4 100644
--- a/packages/auth/integration-tests/__tests__/services/auth-provider/index.spec.ts
+++ b/packages/auth/integration-tests/__tests__/services/auth-provider/index.spec.ts
@@ -1,16 +1,16 @@
import { SqlEntityManager } from "@mikro-orm/postgresql"
-import { AuthProviderService } from "@services"
import { MikroOrmWrapper } from "../../../utils"
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
import { createMedusaContainer } from "@medusajs/utils"
import { asValue } from "awilix"
import ContainerLoader from "../../../../src/loaders/container"
+import { ModulesSdkTypes } from "@medusajs/types"
jest.setTimeout(30000)
describe("AuthProvider Service", () => {
- let service: AuthProviderService
+ let service: ModulesSdkTypes.InternalModuleService
let testManager: SqlEntityManager
let repositoryManager: SqlEntityManager
@@ -180,7 +180,7 @@ describe("AuthProvider Service", () => {
error = e
}
- expect(error.message).toEqual('"authProviderProvider" must be defined')
+ expect(error.message).toEqual("authProvider - provider must be defined")
})
it("should return authProvider based on config select param", async () => {
diff --git a/packages/auth/integration-tests/__tests__/services/auth-user/index.spec.ts b/packages/auth/integration-tests/__tests__/services/auth-user/index.spec.ts
index 07f7aa2426d9e..7dd4afe52e3b0 100644
--- a/packages/auth/integration-tests/__tests__/services/auth-user/index.spec.ts
+++ b/packages/auth/integration-tests/__tests__/services/auth-user/index.spec.ts
@@ -1,12 +1,11 @@
-import { SqlEntityManager } from "@mikro-orm/postgresql"
import { AuthUserService } from "@services"
-
+import ContainerLoader from "../../../../src/loaders/container"
import { MikroOrmWrapper } from "../../../utils"
+import { SqlEntityManager } from "@mikro-orm/postgresql"
+import { asValue } from "awilix"
import { createAuthProviders } from "../../../__fixtures__/auth-provider"
import { createAuthUsers } from "../../../__fixtures__/auth-user"
import { createMedusaContainer } from "@medusajs/utils"
-import { asValue } from "awilix"
-import ContainerLoader from "../../../../src/loaders/container"
jest.setTimeout(30000)
@@ -167,7 +166,7 @@ describe("AuthUser Service", () => {
error = e
}
- expect(error.message).toEqual('"authUserId" must be defined')
+ expect(error.message).toEqual("authUser - id must be defined")
})
})
@@ -229,7 +228,8 @@ describe("AuthUser Service", () => {
{
id: "test",
provider_id: "manual",
- entity_id: "test"
+ entity_id: "test",
+ scope: "store",
},
])
diff --git a/packages/auth/integration-tests/__tests__/services/module/auth-provider.spec.ts b/packages/auth/integration-tests/__tests__/services/module/auth-provider.spec.ts
index 2fdf373176674..37aaa50ad296d 100644
--- a/packages/auth/integration-tests/__tests__/services/module/auth-provider.spec.ts
+++ b/packages/auth/integration-tests/__tests__/services/module/auth-provider.spec.ts
@@ -43,9 +43,8 @@ describe("AuthModuleService - AuthProvider", () => {
describe("listAuthProviders", () => {
it("should list AuthProviders", async () => {
const authProviders = await service.listAuthProviders()
- const serialized = JSON.parse(JSON.stringify(authProviders))
- expect(serialized).toEqual(
+ expect(authProviders).toEqual(
expect.arrayContaining([
expect.objectContaining({
provider: "manual",
@@ -80,9 +79,7 @@ describe("AuthModuleService - AuthProvider", () => {
is_active: true,
})
- const serialized = JSON.parse(JSON.stringify(authProviders))
-
- expect(serialized).toEqual([
+ expect(authProviders).toEqual([
expect.objectContaining({
provider: "manual",
}),
@@ -99,10 +96,9 @@ describe("AuthModuleService - AuthProvider", () => {
describe("listAndCountAuthProviders", () => {
it("should list and count AuthProviders", async () => {
const [authProviders, count] = await service.listAndCountAuthProviders()
- const serialized = JSON.parse(JSON.stringify(authProviders))
expect(count).toEqual(4)
- expect(serialized).toEqual([
+ expect(authProviders).toEqual([
expect.objectContaining({
provider: "manual",
}),
@@ -136,10 +132,8 @@ describe("AuthModuleService - AuthProvider", () => {
is_active: true,
})
- const serialized = JSON.parse(JSON.stringify(authProviders))
-
expect(count).toEqual(3)
- expect(serialized).toEqual([
+ expect(authProviders).toEqual([
expect.objectContaining({
provider: "manual",
}),
@@ -171,9 +165,7 @@ describe("AuthModuleService - AuthProvider", () => {
select: ["provider"],
})
- const serialized = JSON.parse(JSON.stringify(authProvider))
-
- expect(serialized).toEqual({
+ expect(authProvider).toEqual({
provider,
})
})
@@ -201,7 +193,7 @@ describe("AuthModuleService - AuthProvider", () => {
error = e
}
- expect(error.message).toEqual('"authProviderProvider" must be defined')
+ expect(error.message).toEqual("authProvider - provider must be defined")
})
})
@@ -209,7 +201,7 @@ describe("AuthModuleService - AuthProvider", () => {
const provider = "manual"
it("should delete the authProviders given a provider successfully", async () => {
- await service.deleteAuthProvider([provider])
+ await service.deleteAuthProviders([provider])
const authProviders = await service.listAuthProviders({
provider: [provider],
diff --git a/packages/auth/integration-tests/__tests__/services/module/auth-user.spec.ts b/packages/auth/integration-tests/__tests__/services/module/auth-user.spec.ts
index 86fde3c04bab6..3ca27ed83e01d 100644
--- a/packages/auth/integration-tests/__tests__/services/module/auth-user.spec.ts
+++ b/packages/auth/integration-tests/__tests__/services/module/auth-user.spec.ts
@@ -43,17 +43,16 @@ describe("AuthModuleService - AuthUser", () => {
describe("listAuthUsers", () => {
it("should list authUsers", async () => {
const authUsers = await service.listAuthUsers()
- const serialized = JSON.parse(JSON.stringify(authUsers))
- expect(serialized).toEqual([
+ expect(authUsers).toEqual([
expect.objectContaining({
- provider: "manual",
+ provider: { provider: "manual" },
}),
expect.objectContaining({
- provider: "manual",
+ provider: { provider: "manual" },
}),
expect.objectContaining({
- provider: "store",
+ provider: { provider: "store" },
}),
])
})
@@ -75,9 +74,7 @@ describe("AuthModuleService - AuthUser", () => {
provider_id: "manual",
})
- const serialized = JSON.parse(JSON.stringify(authUsers))
-
- expect(serialized).toEqual([
+ expect(authUsers).toEqual([
expect.objectContaining({
id: "test-id",
}),
@@ -91,18 +88,17 @@ describe("AuthModuleService - AuthUser", () => {
describe("listAndCountAuthUsers", () => {
it("should list and count authUsers", async () => {
const [authUsers, count] = await service.listAndCountAuthUsers()
- const serialized = JSON.parse(JSON.stringify(authUsers))
expect(count).toEqual(3)
- expect(serialized).toEqual([
+ expect(authUsers).toEqual([
expect.objectContaining({
- provider: "manual",
+ provider: { provider: "manual" },
}),
expect.objectContaining({
- provider: "manual",
+ provider: { provider: "manual" },
}),
expect.objectContaining({
- provider: "store",
+ provider: { provider: "store" },
}),
])
})
@@ -171,7 +167,7 @@ describe("AuthModuleService - AuthUser", () => {
error = e
}
- expect(error.message).toEqual('"authUserId" must be defined')
+ expect(error.message).toEqual("authUser - id must be defined")
})
it("should return authUser based on config select param", async () => {
@@ -179,9 +175,7 @@ describe("AuthModuleService - AuthUser", () => {
select: ["id"],
})
- const serialized = JSON.parse(JSON.stringify(authUser))
-
- expect(serialized).toEqual({
+ expect(authUser).toEqual({
id,
})
})
@@ -191,7 +185,7 @@ describe("AuthModuleService - AuthUser", () => {
const id = "test-id"
it("should delete the authUsers given an id successfully", async () => {
- await service.deleteAuthUser([id])
+ await service.deleteAuthUsers([id])
const authUsers = await service.listAuthUsers({
id: [id],
@@ -246,6 +240,7 @@ describe("AuthModuleService - AuthUser", () => {
id: "test",
provider_id: "manual",
entity_id: "test",
+ scope: "store",
},
])
diff --git a/packages/auth/integration-tests/__tests__/services/module/providers.spec.ts b/packages/auth/integration-tests/__tests__/services/module/providers.spec.ts
index 556db598380d5..b118e54ac026e 100644
--- a/packages/auth/integration-tests/__tests__/services/module/providers.spec.ts
+++ b/packages/auth/integration-tests/__tests__/services/module/providers.spec.ts
@@ -45,9 +45,8 @@ describe("AuthModuleService - AuthProvider", () => {
describe("listAuthProviders", () => {
it("should list default AuthProviders registered by loaders", async () => {
const authProviders = await service.listAuthProviders()
- const serialized = JSON.parse(JSON.stringify(authProviders))
- expect(serialized).toEqual(
+ expect(authProviders).toEqual(
expect.arrayContaining([
expect.objectContaining({
provider: "emailpass",
@@ -83,7 +82,7 @@ describe("AuthModuleService - AuthProvider", () => {
const { success, error } = await service.authenticate(
"emailpass",
{
- scope: "non-existing",
+ authScope: "non-existing",
} as any
)
diff --git a/packages/auth/integration-tests/__tests__/services/providers/username-password.spec.ts b/packages/auth/integration-tests/__tests__/services/providers/username-password.spec.ts
index 3cd76abcd9408..7e3955d71b9b5 100644
--- a/packages/auth/integration-tests/__tests__/services/providers/username-password.spec.ts
+++ b/packages/auth/integration-tests/__tests__/services/providers/username-password.spec.ts
@@ -1,6 +1,6 @@
-import { AuthenticationInput, IAuthModuleService } from "@medusajs/types"
import { MedusaModule, Modules } from "@medusajs/modules-sdk"
+import { IAuthModuleService } from "@medusajs/types"
import { MikroOrmWrapper } from "../../../utils"
import Scrypt from "scrypt-kdf"
import { SqlEntityManager } from "@mikro-orm/postgresql"
@@ -62,6 +62,7 @@ describe("AuthModuleService - AuthProvider", () => {
{
provider: "emailpass",
entity_id: email,
+ scope: "store",
provider_metadata: {
password: passwordHash,
},
@@ -73,8 +74,8 @@ describe("AuthModuleService - AuthProvider", () => {
email: "test@test.com",
password: password,
},
- scope: "store",
- })
+ authScope: "store",
+ } as any)
expect(res).toEqual({
success: true,
@@ -92,8 +93,8 @@ describe("AuthModuleService - AuthProvider", () => {
const res = await service.authenticate("emailpass", {
body: { email: "test@test.com" },
- scope: "store",
- })
+ authScope: "store",
+ } as any)
expect(res).toEqual({
success: false,
@@ -106,8 +107,8 @@ describe("AuthModuleService - AuthProvider", () => {
const res = await service.authenticate("emailpass", {
body: { password: "supersecret" },
- scope: "store",
- })
+ authScope: "store",
+ } as any)
expect(res).toEqual({
success: false,
@@ -127,6 +128,7 @@ describe("AuthModuleService - AuthProvider", () => {
// Add authenticated user
{
provider: "emailpass",
+ scope: "store",
entity_id: email,
provider_metadata: {
password_hash: passwordHash,
@@ -139,8 +141,8 @@ describe("AuthModuleService - AuthProvider", () => {
email: "test@test.com",
password: "password",
},
- scope: "store",
- })
+ authScope: "store",
+ } as any)
expect(res).toEqual({
success: false,
diff --git a/packages/auth/package.json b/packages/auth/package.json
index ac68f58918135..4516db7edd6ae 100644
--- a/packages/auth/package.json
+++ b/packages/auth/package.json
@@ -55,7 +55,7 @@
"@mikro-orm/migrations": "5.9.7",
"@mikro-orm/postgresql": "5.9.7",
"awilix": "^8.0.0",
- "dotenv": "^16.1.4",
+ "dotenv": "16.3.1",
"jsonwebtoken": "^9.0.2",
"knex": "2.4.2",
"scrypt-kdf": "^2.0.1",
diff --git a/packages/auth/src/migrations/.snapshot-medusa-authentication.json b/packages/auth/src/migrations/.snapshot-medusa-auth.json
similarity index 91%
rename from packages/auth/src/migrations/.snapshot-medusa-authentication.json
rename to packages/auth/src/migrations/.snapshot-medusa-auth.json
index a31fe796e7234..294b0a9ba5d4b 100644
--- a/packages/auth/src/migrations/.snapshot-medusa-authentication.json
+++ b/packages/auth/src/migrations/.snapshot-medusa-auth.json
@@ -24,20 +24,14 @@
"nullable": false,
"mappedType": "text"
},
- "domain": {
- "name": "domain",
+ "scope": {
+ "name": "scope",
"type": "text",
"unsigned": false,
"autoincrement": false,
"primary": false,
- "nullable": false,
- "default": "'all'",
- "enumItems": [
- "all",
- "store",
- "admin"
- ],
- "mappedType": "enum"
+ "nullable": true,
+ "mappedType": "text"
},
"config": {
"name": "config",
@@ -104,6 +98,15 @@
"nullable": true,
"mappedType": "text"
},
+ "scope": {
+ "name": "scope",
+ "type": "text",
+ "unsigned": false,
+ "autoincrement": false,
+ "primary": false,
+ "nullable": false,
+ "mappedType": "text"
+ },
"user_metadata": {
"name": "user_metadata",
"type": "jsonb",
@@ -119,7 +122,7 @@
"unsigned": false,
"autoincrement": false,
"primary": false,
- "nullable": true,
+ "nullable": false,
"mappedType": "json"
},
"provider_metadata": {
@@ -136,9 +139,10 @@
"schema": "public",
"indexes": [
{
- "keyName": "IDX_auth_user_provider_entity_id",
+ "keyName": "IDX_auth_user_provider_scope_entity_id",
"columnNames": [
"provider_id",
+ "scope",
"entity_id"
],
"composite": true,
diff --git a/packages/auth/src/migrations/Migration20240122041959.ts b/packages/auth/src/migrations/Migration20240122041959.ts
deleted file mode 100644
index 15f1526572d4f..0000000000000
--- a/packages/auth/src/migrations/Migration20240122041959.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { Migration } from "@mikro-orm/migrations"
-
-export class Migration20240122041959 extends Migration {
- async up(): Promise {
- this.addSql(
- 'create table if not exists "auth_provider" ("provider" text not null, "name" text not null, "domain" text check ("domain" in (\'all\', \'store\', \'admin\')) not null default \'all\', "config" jsonb null, "is_active" boolean not null default false, constraint "auth_provider_pkey" primary key ("provider"));'
- )
-
- this.addSql(
- 'create table if not exists "auth_user" ("id" text not null, "entity_id" text not null, "provider_id" text null, "user_metadata" jsonb null, "app_metadata" jsonb null, "provider_metadata" jsonb null, constraint "auth_user_pkey" primary key ("id"));'
- )
- this.addSql(
- 'alter table "auth_user" add constraint "IDX_auth_user_provider_entity_id" unique ("provider_id", "entity_id");'
- )
-
- this.addSql(
- 'alter table "auth_user" add constraint "auth_user_provider_id_foreign" foreign key ("provider_id") references "auth_provider" ("provider") on delete cascade;'
- )
- }
-
- async down(): Promise {
- this.addSql(
- 'alter table "auth_user" drop constraint if exists "auth_user_provider_id_foreign";'
- )
-
- this.addSql('drop table if exists "auth_provider" cascade;')
-
- this.addSql('drop table if exists "auth_user" cascade;')
- }
-}
diff --git a/packages/auth/src/migrations/Migration20240201100135.ts b/packages/auth/src/migrations/Migration20240201100135.ts
new file mode 100644
index 0000000000000..de100203d9a04
--- /dev/null
+++ b/packages/auth/src/migrations/Migration20240201100135.ts
@@ -0,0 +1,22 @@
+import { Migration } from '@mikro-orm/migrations';
+
+export class Migration20240201100135 extends Migration {
+
+ async up(): Promise {
+ this.addSql('create table "auth_provider" ("provider" text not null, "name" text not null, "scope" text null, "config" jsonb null, "is_active" boolean not null default false, constraint "auth_provider_pkey" primary key ("provider"));');
+
+ this.addSql('create table "auth_user" ("id" text not null, "entity_id" text not null, "provider_id" text null, "scope" text not null, "user_metadata" jsonb null, "app_metadata" jsonb not null, "provider_metadata" jsonb null, constraint "auth_user_pkey" primary key ("id"));');
+ this.addSql('alter table "auth_user" add constraint "IDX_auth_user_provider_scope_entity_id" unique ("provider_id", "scope", "entity_id");');
+
+ this.addSql('alter table "auth_user" add constraint "auth_user_provider_id_foreign" foreign key ("provider_id") references "auth_provider" ("provider") on delete cascade;');
+ }
+
+ async down(): Promise {
+ this.addSql('alter table "auth_user" drop constraint "auth_user_provider_id_foreign";');
+
+ this.addSql('drop table if exists "auth_provider" cascade;');
+
+ this.addSql('drop table if exists "auth_user" cascade;');
+ }
+
+}
diff --git a/packages/auth/src/models/auth-provider.ts b/packages/auth/src/models/auth-provider.ts
index 0827186069bbd..39ba51823585d 100644
--- a/packages/auth/src/models/auth-provider.ts
+++ b/packages/auth/src/models/auth-provider.ts
@@ -20,8 +20,8 @@ export default class AuthProvider {
@Property({ columnType: "text" })
name: string
- @Enum({ items: () => ProviderDomain, default: ProviderDomain.ALL })
- domain: ProviderDomain = ProviderDomain.ALL
+ @Property({ columnType: "text", nullable: true })
+ scope: string
@Property({ columnType: "jsonb", nullable: true })
config: Record | null = null
diff --git a/packages/auth/src/models/auth-user.ts b/packages/auth/src/models/auth-user.ts
index 0c10053175fae..122462c26cdf1 100644
--- a/packages/auth/src/models/auth-user.ts
+++ b/packages/auth/src/models/auth-user.ts
@@ -17,7 +17,10 @@ import { generateEntityId } from "@medusajs/utils"
type OptionalFields = "provider_metadata" | "app_metadata" | "user_metadata"
@Entity()
-@Unique({ properties: ["provider","entity_id" ], name: "IDX_auth_user_provider_entity_id" })
+@Unique({
+ properties: ["provider", "scope", "entity_id"],
+ name: "IDX_auth_user_provider_scope_entity_id",
+})
export default class AuthUser {
[OptionalProps]: OptionalFields
@@ -34,14 +37,17 @@ export default class AuthUser {
})
provider: AuthProvider
+ @Property({ columnType: "text" })
+ scope: string
+
@Property({ columnType: "jsonb", nullable: true })
user_metadata: Record | null
- @Property({ columnType: "jsonb", nullable: true })
- app_metadata: Record | null
+ @Property({ columnType: "jsonb" })
+ app_metadata: Record = {}
@Property({ columnType: "jsonb", nullable: true })
- provider_metadata: Record | null
+ provider_metadata: Record | null = null
@BeforeCreate()
onCreate() {
diff --git a/packages/auth/src/providers/email-password.ts b/packages/auth/src/providers/email-password.ts
index 3e9760f991041..da2617ef2a81f 100644
--- a/packages/auth/src/providers/email-password.ts
+++ b/packages/auth/src/providers/email-password.ts
@@ -1,4 +1,8 @@
-import { AbstractAuthModuleProvider, isString } from "@medusajs/utils"
+import {
+ AbstractAuthModuleProvider,
+ MedusaError,
+ isString,
+} from "@medusajs/utils"
import { AuthenticationInput, AuthenticationResponse } from "@medusajs/types"
import { AuthUserService } from "@services"
@@ -16,6 +20,17 @@ class EmailPasswordProvider extends AbstractAuthModuleProvider {
this.authUserSerivce_ = authUserService
}
+ private getHashConfig(scope: string) {
+ const scopeConfig = this.scopes_[scope].hashConfig as
+ | Scrypt.ScryptParams
+ | undefined
+
+ const defaultHashConfig = { logN: 15, r: 8, p: 1 }
+
+ // Return custom defined hash config or default hash parameters
+ return scopeConfig ?? defaultHashConfig
+ }
+
async authenticate(
userData: AuthenticationInput
): Promise {
@@ -34,11 +49,38 @@ class EmailPasswordProvider extends AbstractAuthModuleProvider {
error: "Email should be a string",
}
}
-
- const authUser = await this.authUserSerivce_.retrieveByProviderAndEntityId(
- email,
- EmailPasswordProvider.PROVIDER
- )
+ let authUser
+
+ try {
+ authUser = await this.authUserSerivce_.retrieveByProviderAndEntityId(
+ email,
+ EmailPasswordProvider.PROVIDER
+ )
+ } catch (error) {
+ if (error.type === MedusaError.Types.NOT_FOUND) {
+ const password_hash = await Scrypt.kdf(
+ password,
+ this.getHashConfig(userData.authScope)
+ )
+
+ const [createdAuthUser] = await this.authUserSerivce_.create([
+ {
+ entity_id: email,
+ provider: EmailPasswordProvider.PROVIDER,
+ scope: userData.authScope,
+ provider_metadata: {
+ password: password_hash.toString("base64"),
+ },
+ },
+ ])
+
+ return {
+ success: true,
+ authUser: JSON.parse(JSON.stringify(createdAuthUser)),
+ }
+ }
+ return { success: false, error: error.message }
+ }
const password_hash = authUser.provider_metadata?.password
diff --git a/packages/auth/src/providers/google.ts b/packages/auth/src/providers/google.ts
index 5a94eb992260f..77f7d9d8788eb 100644
--- a/packages/auth/src/providers/google.ts
+++ b/packages/auth/src/providers/google.ts
@@ -1,20 +1,19 @@
+import { AbstractAuthModuleProvider, MedusaError } from "@medusajs/utils"
import {
- AbstractAuthModuleProvider,
- MedusaError,
-} from "@medusajs/utils"
-import {
- AuthProviderScope,
AuthenticationInput,
AuthenticationResponse,
+ AuthProviderScope,
+ ModulesSdkTypes,
} from "@medusajs/types"
-import { AuthProviderService, AuthUserService } from "@services"
+import { AuthUserService } from "@services"
import jwt, { JwtPayload } from "jsonwebtoken"
+
import { AuthorizationCode } from "simple-oauth2"
import url from "url"
type InjectedDependencies = {
authUserService: AuthUserService
- authProviderService: AuthProviderService
+ authProviderService: ModulesSdkTypes.InternalModuleService
}
type ProviderConfig = {
@@ -27,13 +26,13 @@ class GoogleProvider extends AbstractAuthModuleProvider {
public static PROVIDER = "google"
public static DISPLAY_NAME = "Google Authentication"
- protected readonly authUserSerivce_: AuthUserService
- protected readonly authProviderService_: AuthProviderService
+ protected readonly authUserService_: AuthUserService
+ protected readonly authProviderService_: ModulesSdkTypes.InternalModuleService
constructor({ authUserService, authProviderService }: InjectedDependencies) {
super(arguments[0])
- this.authUserSerivce_ = authUserService
+ this.authUserService_ = authUserService
this.authProviderService_ = authProviderService
}
@@ -78,7 +77,7 @@ class GoogleProvider extends AbstractAuthModuleProvider {
const code = req.query?.code ?? req.body?.code
- return await this.validateCallbackToken(code, req.scope, config)
+ return await this.validateCallbackToken(code, req.authScope, config)
}
// abstractable
@@ -91,20 +90,21 @@ class GoogleProvider extends AbstractAuthModuleProvider {
let authUser
try {
- authUser = await this.authUserSerivce_.retrieveByProviderAndEntityId(
+ authUser = await this.authUserService_.retrieveByProviderAndEntityId(
entity_id,
GoogleProvider.PROVIDER
)
} catch (error) {
if (error.type === MedusaError.Types.NOT_FOUND) {
- authUser = await this.authUserSerivce_.create([
+ const [createdAuthUser] = await this.authUserService_.create([
{
entity_id,
- provider_id: GoogleProvider.PROVIDER,
+ provider: GoogleProvider.PROVIDER,
user_metadata: jwtData!.payload,
- app_metadata: { scope },
+ scope,
},
])
+ authUser = createdAuthUser
} else {
return { success: false, error: error.message }
}
@@ -135,24 +135,20 @@ class GoogleProvider extends AbstractAuthModuleProvider {
}
}
- private getConfigFromScope(config: AuthProviderScope): ProviderConfig {
- const providerConfig: Partial = {}
+ private getConfigFromScope(
+ config: AuthProviderScope & Partial
+ ): ProviderConfig {
+ const providerConfig: Partial = { ...config }
- if (config.clientId) {
- providerConfig.clientID = config.clientId
- } else {
+ if (!providerConfig.clientID) {
throw new Error("Google clientID is required")
}
- if (config.clientSecret) {
- providerConfig.clientSecret = config.clientSecret
- } else {
+ if (!providerConfig.clientSecret) {
throw new Error("Google clientSecret is required")
}
- if (config.callbackURL) {
- providerConfig.callbackURL = config.callbackUrl
- } else {
+ if (!providerConfig.callbackURL) {
throw new Error("Google callbackUrl is required")
}
@@ -160,9 +156,8 @@ class GoogleProvider extends AbstractAuthModuleProvider {
}
private originalURL(req: AuthenticationInput) {
- const tls = req.connection.encrypted
const host = req.headers.host
- const protocol = tls ? "https" : "http"
+ const protocol = req.protocol
const path = req.url || ""
return protocol + "://" + host + path
@@ -173,7 +168,7 @@ class GoogleProvider extends AbstractAuthModuleProvider {
): Promise {
await this.authProviderService_.retrieve(GoogleProvider.PROVIDER)
- const scopeConfig = this.scopes_[req.scope]
+ const scopeConfig = this.scopes_[req.authScope]
const config = this.getConfigFromScope(scopeConfig)
diff --git a/packages/auth/src/services/auth-module.ts b/packages/auth/src/services/auth-module.ts
index 3310c28c1f407..995ec3b734dc4 100644
--- a/packages/auth/src/services/auth-module.ts
+++ b/packages/auth/src/services/auth-module.ts
@@ -1,35 +1,35 @@
import jwt from "jsonwebtoken"
import {
+ AuthenticationInput,
+ AuthenticationResponse,
AuthProviderDTO,
AuthTypes,
AuthUserDTO,
- AuthenticationInput,
- AuthenticationResponse,
Context,
CreateAuthProviderDTO,
CreateAuthUserDTO,
DAL,
- FilterableAuthProviderProps,
- FilterableAuthUserProps,
- FindConfig,
InternalModuleDeclaration,
JWTGenerationOptions,
- MedusaContainer,
ModuleJoinerConfig,
+ ModulesSdkTypes,
UpdateAuthUserDTO,
} from "@medusajs/types"
+
+import { AuthProvider, AuthUser } from "@models"
+
+import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
+
import {
AbstractAuthModuleProvider,
InjectManager,
InjectTransactionManager,
MedusaContext,
MedusaError,
+ ModulesSdkUtils,
} from "@medusajs/utils"
-import { AuthProvider, AuthUser } from "@models"
-import { AuthProviderService, AuthUserService } from "@services"
import { ServiceTypes } from "@types"
-import { joinerConfig } from "../joiner-config"
type AuthModuleOptions = {
jwt_secret: string
@@ -42,28 +42,32 @@ type AuthJWTPayload = {
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
- authUserService: AuthUserService
- authProviderService: AuthProviderService
+ authUserService: ModulesSdkTypes.InternalModuleService
+ authProviderService: ModulesSdkTypes.InternalModuleService
}
+const generateMethodForModels = [AuthProvider, AuthUser]
+
export default class AuthModuleService<
- TAuthUser extends AuthUser = AuthUser,
- TAuthProvider extends AuthProvider = AuthProvider
-> implements AuthTypes.IAuthModuleService
+ TAuthUser extends AuthUser = AuthUser,
+ TAuthProvider extends AuthProvider = AuthProvider
+ >
+ extends ModulesSdkUtils.abstractModuleServiceFactory<
+ InjectedDependencies,
+ AuthTypes.AuthProviderDTO,
+ {
+ AuthUser: { dto: AuthUserDTO }
+ AuthProvider: { dto: AuthProviderDTO }
+ }
+ >(AuthProvider, generateMethodForModels, entityNameToLinkableKeysMap)
+ implements AuthTypes.IAuthModuleService
{
- __joinerConfig(): ModuleJoinerConfig {
- return joinerConfig
- }
-
__hooks = {
onApplicationStart: async () => await this.createProvidersOnLoad(),
}
-
- protected __container__: MedusaContainer
protected baseRepository_: DAL.RepositoryService
-
- protected authUserService_: AuthUserService
- protected authProviderService_: AuthProviderService
+ protected authUserService_: ModulesSdkTypes.InternalModuleService
+ protected authProviderService_: ModulesSdkTypes.InternalModuleService
protected options_: AuthModuleOptions
constructor(
@@ -75,66 +79,17 @@ export default class AuthModuleService<
options: AuthModuleOptions,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
- this.__container__ = arguments[0]
+ // @ts-ignore
+ super(...arguments)
+
this.baseRepository_ = baseRepository
this.authUserService_ = authUserService
this.authProviderService_ = authProviderService
this.options_ = options
}
- async retrieveAuthProvider(
- provider: string,
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const authProvider = await this.authProviderService_.retrieve(
- provider,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize(
- authProvider,
- { populate: true }
- )
- }
-
- async listAuthProviders(
- filters: FilterableAuthProviderProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const authProviders = await this.authProviderService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize(
- authProviders,
- { populate: true }
- )
- }
-
- @InjectManager("baseRepository_")
- async listAndCountAuthProviders(
- filters: FilterableAuthProviderProps = {},
- config: FindConfig,
- @MedusaContext() sharedContext: Context = {}
- ): Promise<[AuthTypes.AuthProviderDTO[], number]> {
- const [authProviders, count] = await this.authProviderService_.listAndCount(
- filters,
- config,
- sharedContext
- )
-
- return [
- await this.baseRepository_.serialize(
- authProviders,
- { populate: true }
- ),
- count,
- ]
+ __joinerConfig(): ModuleJoinerConfig {
+ return joinerConfig
}
async generateJwtToken(
@@ -205,18 +160,11 @@ export default class AuthModuleService<
return Array.isArray(data) ? serializedProviders : serializedProviders[0]
}
- @InjectTransactionManager("baseRepository_")
- protected async createAuthProviders_(
- data: any[],
- @MedusaContext() sharedContext: Context
- ): Promise {
- return await this.authProviderService_.create(data, sharedContext)
- }
-
updateAuthProvider(
data: AuthTypes.UpdateAuthProviderDTO[],
sharedContext?: Context
): Promise
+
updateAuthProvider(
data: AuthTypes.UpdateAuthProviderDTO,
sharedContext?: Context
@@ -247,78 +195,11 @@ export default class AuthModuleService<
return await this.authProviderService_.update(data, sharedContext)
}
- @InjectTransactionManager("baseRepository_")
- async deleteAuthProvider(
- ids: string[],
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- await this.authProviderService_.delete(ids, sharedContext)
- }
-
- @InjectManager("baseRepository_")
- async retrieveAuthUser(
- id: string,
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const authUser = await this.authUserService_.retrieve(
- id,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize(
- authUser,
- {
- exclude: ["password_hash"],
- }
- )
- }
-
- @InjectManager("baseRepository_")
- async listAuthUsers(
- filters: FilterableAuthUserProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const authUsers = await this.authUserService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize(
- authUsers,
- {
- populate: true,
- }
- )
- }
-
- @InjectManager("baseRepository_")
- async listAndCountAuthUsers(
- filters: FilterableAuthUserProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise<[AuthUserDTO[], number]> {
- const [authUsers, count] = await this.authUserService_.listAndCount(
- filters,
- config,
- sharedContext
- )
-
- return [
- await this.baseRepository_.serialize(authUsers, {
- populate: true,
- }),
- count,
- ]
- }
-
createAuthUser(
data: CreateAuthUserDTO[],
sharedContext?: Context
): Promise
+
createAuthUser(
data: CreateAuthUserDTO,
sharedContext?: Context
@@ -342,23 +223,17 @@ export default class AuthModuleService<
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
}
- @InjectTransactionManager("baseRepository_")
- protected async createAuthUsers_(
- data: CreateAuthUserDTO[],
- @MedusaContext() sharedContext: Context
- ): Promise {
- return await this.authUserService_.create(data, sharedContext)
- }
-
updateAuthUser(
data: UpdateAuthUserDTO[],
sharedContext?: Context
): Promise
+
updateAuthUser(
data: UpdateAuthUserDTO,
sharedContext?: Context
): Promise
+ // TODO: should be pluralized, see convention about the methods naming or the abstract module service interface definition @engineering
@InjectManager("baseRepository_")
async updateAuthUser(
data: UpdateAuthUserDTO | UpdateAuthUserDTO[],
@@ -385,17 +260,9 @@ export default class AuthModuleService<
return await this.authUserService_.update(data, sharedContext)
}
- @InjectTransactionManager("baseRepository_")
- async deleteAuthUser(
- ids: string[],
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- await this.authUserService_.delete(ids, sharedContext)
- }
-
protected getRegisteredAuthenticationProvider(
provider: string,
- { scope }: AuthenticationInput
+ { authScope }: AuthenticationInput
): AbstractAuthModuleProvider {
let containerProvider: AbstractAuthModuleProvider
try {
@@ -407,7 +274,7 @@ export default class AuthModuleService<
)
}
- containerProvider.validateScope(scope)
+ containerProvider.validateScope(authScope)
return containerProvider
}
@@ -448,6 +315,22 @@ export default class AuthModuleService<
}
}
+ @InjectTransactionManager("baseRepository_")
+ protected async createAuthProviders_(
+ data: any[],
+ @MedusaContext() sharedContext: Context
+ ): Promise {
+ return await this.authProviderService_.create(data, sharedContext)
+ }
+
+ @InjectTransactionManager("baseRepository_")
+ protected async createAuthUsers_(
+ data: CreateAuthUserDTO[],
+ @MedusaContext() sharedContext: Context
+ ): Promise {
+ return await this.authUserService_.create(data, sharedContext)
+ }
+
private async createProvidersOnLoad() {
const providersToLoad = this.__container__["auth_providers"]
diff --git a/packages/auth/src/services/auth-provider.ts b/packages/auth/src/services/auth-provider.ts
deleted file mode 100644
index 241fb56e800df..0000000000000
--- a/packages/auth/src/services/auth-provider.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { DAL } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { AuthProvider } from "@models"
-
-import { ServiceTypes } from "@types"
-
-type InjectedDependencies = {
- authProviderRepository: DAL.RepositoryService
-}
-
-export default class AuthProviderService<
- TEntity extends AuthProvider = AuthProvider
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: ServiceTypes.CreateAuthProviderDTO
- update: ServiceTypes.UpdateAuthProviderDTO
- }
->(AuthProvider) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/auth/src/services/auth-user.ts b/packages/auth/src/services/auth-user.ts
index 7625415da9360..a8e6fcc264df4 100644
--- a/packages/auth/src/services/auth-user.ts
+++ b/packages/auth/src/services/auth-user.ts
@@ -1,4 +1,10 @@
-import { AuthTypes, Context, DAL, FindConfig } from "@medusajs/types"
+import {
+ AuthTypes,
+ Context,
+ DAL,
+ FindConfig,
+ RepositoryService,
+} from "@medusajs/types"
import {
InjectManager,
MedusaContext,
@@ -6,7 +12,6 @@ import {
ModulesSdkUtils,
} from "@medusajs/utils"
import { AuthUser } from "@models"
-import { ServiceTypes, RepositoryTypes } from "@types"
type InjectedDependencies = {
authUserRepository: DAL.RepositoryService
@@ -14,13 +19,11 @@ type InjectedDependencies = {
export default class AuthUserService<
TEntity extends AuthUser = AuthUser
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: ServiceTypes.CreateAuthUserDTO
- }
->(AuthUser) {
- protected readonly authUserRepository_: RepositoryTypes.IAuthUserRepository
+> extends ModulesSdkUtils.internalModuleServiceFactory(
+ AuthUser
+) {
+ protected readonly authUserRepository_: RepositoryService
+
constructor(container: InjectedDependencies) {
// @ts-ignore
super(...arguments)
@@ -28,9 +31,7 @@ export default class AuthUserService<
}
@InjectManager("authUserRepository_")
- async retrieveByProviderAndEntityId<
- TEntityMethod = AuthTypes.AuthUserDTO
- >(
+ async retrieveByProviderAndEntityId(
entityId: string,
provider: string,
config: FindConfig = {},
diff --git a/packages/auth/src/services/index.ts b/packages/auth/src/services/index.ts
index 03a3c0933defc..547d1a5466ca0 100644
--- a/packages/auth/src/services/index.ts
+++ b/packages/auth/src/services/index.ts
@@ -1,3 +1,2 @@
export { default as AuthModuleService } from "./auth-module"
-export { default as AuthProviderService } from "./auth-provider"
export { default as AuthUserService } from "./auth-user"
diff --git a/packages/auth/src/types/repositories/index.ts b/packages/auth/src/types/repositories/index.ts
index 86ed73825729d..b4282c985c6a3 100644
--- a/packages/auth/src/types/repositories/index.ts
+++ b/packages/auth/src/types/repositories/index.ts
@@ -1,28 +1,2 @@
-import { AuthProvider, AuthUser } from "@models"
-import { CreateAuthProviderDTO, UpdateAuthProviderDTO } from "./auth-provider"
-import { DAL } from "@medusajs/types"
-import { CreateAuthUserDTO, UpdateAuthUserDTO } from "./auth-user"
-
export * from "./auth-user"
export * from "./auth-provider"
-
-// eslint-disable-next-line @typescript-eslint/no-empty-interface
-export interface IAuthProviderRepository<
- TEntity extends AuthProvider = AuthProvider
-> extends DAL.RepositoryService<
- TEntity,
- {
- create: CreateAuthProviderDTO
- update: UpdateAuthProviderDTO
- }
- > {}
-
-// eslint-disable-next-line @typescript-eslint/no-empty-interface
-export interface IAuthUserRepository
- extends DAL.RepositoryService<
- TEntity,
- {
- create: CreateAuthUserDTO
- update: UpdateAuthUserDTO
- }
- > {}
diff --git a/packages/auth/src/types/services/auth-provider.ts b/packages/auth/src/types/services/auth-provider.ts
index 8ef5d9b3b9bdd..dc400222e43a1 100644
--- a/packages/auth/src/types/services/auth-provider.ts
+++ b/packages/auth/src/types/services/auth-provider.ts
@@ -1,7 +1,7 @@
export type AuthProviderDTO = {
provider: string
name: string
- domain: ProviderDomain
+ scope: string
is_active: boolean
config: Record
}
@@ -9,7 +9,7 @@ export type AuthProviderDTO = {
export type CreateAuthProviderDTO = {
provider: string
name: string
- domain?: ProviderDomain
+ scope?: string
is_active?: boolean
config?: Record
}
@@ -17,15 +17,8 @@ export type CreateAuthProviderDTO = {
export type UpdateAuthProviderDTO = {
provider: string
name?: string
- domain?: ProviderDomain
is_active?: boolean
config?: Record
}
-export enum ProviderDomain {
- ALL = "all",
- STORE = "store",
- ADMIN = "admin",
-}
-
export type FilterableAuthProviderProps = {}
diff --git a/packages/auth/src/types/services/auth-user.ts b/packages/auth/src/types/services/auth-user.ts
index c059e980f8b9c..bab3e0c2e4f9d 100644
--- a/packages/auth/src/types/services/auth-user.ts
+++ b/packages/auth/src/types/services/auth-user.ts
@@ -4,6 +4,7 @@ export type AuthUserDTO = {
id: string
provider_id: string
entity_id: string
+ scope: string
provider: AuthProviderDTO
provider_metadata?: Record
user_metadata: Record
@@ -12,7 +13,8 @@ export type AuthUserDTO = {
export type CreateAuthUserDTO = {
entity_id: string
- provider_id: string
+ provider: string
+ scope: string
provider_metadata?: Record
user_metadata?: Record
app_metadata?: Record
diff --git a/packages/cart/src/services/address.ts b/packages/cart/src/services/address.ts
deleted file mode 100644
index 383a07707bc37..0000000000000
--- a/packages/cart/src/services/address.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { DAL } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { Address } from "@models"
-import { CreateAddressDTO, UpdateAddressDTO } from "@types"
-
-type InjectedDependencies = {
- addressRepository: DAL.RepositoryService
-}
-
-export default class AddressService<
- TEntity extends Address = Address
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CreateAddressDTO
- update: UpdateAddressDTO
- }
->(Address) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/cart/src/services/cart-module.ts b/packages/cart/src/services/cart-module.ts
index e3eaff368aa6f..79274eed6b21d 100644
--- a/packages/cart/src/services/cart-module.ts
+++ b/packages/cart/src/services/cart-module.ts
@@ -3,20 +3,22 @@ import {
Context,
DAL,
FilterableLineItemTaxLineProps,
- FindConfig,
ICartModuleService,
InternalModuleDeclaration,
ModuleJoinerConfig,
+ ModulesSdkTypes,
} from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
- MedusaContext,
- MedusaError,
isObject,
isString,
+ MedusaContext,
+ MedusaError,
+ ModulesSdkUtils,
} from "@medusajs/utils"
import {
+ Address,
Cart,
LineItem,
LineItemAdjustment,
@@ -25,32 +27,73 @@ import {
ShippingMethodAdjustment,
ShippingMethodTaxLine,
} from "@models"
-import { CreateLineItemDTO, UpdateLineItemDTO } from "@types"
-import { joinerConfig } from "../joiner-config"
-import * as services from "../services"
+import {
+ CreateLineItemDTO,
+ CreateLineItemTaxLineDTO,
+ CreateShippingMethodDTO,
+ CreateShippingMethodTaxLineDTO,
+ UpdateLineItemDTO,
+ UpdateLineItemTaxLineDTO,
+ UpdateShippingMethodTaxLineDTO,
+} from "@types"
+import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
- cartService: services.CartService
- addressService: services.AddressService
- lineItemService: services.LineItemService
- shippingMethodAdjustmentService: services.ShippingMethodAdjustmentService
- shippingMethodService: services.ShippingMethodService
- lineItemAdjustmentService: services.LineItemAdjustmentService
- lineItemTaxLineService: services.LineItemTaxLineService
- shippingMethodTaxLineService: services.ShippingMethodTaxLineService
+ cartService: ModulesSdkTypes.InternalModuleService
+ addressService: ModulesSdkTypes.InternalModuleService
+ lineItemService: ModulesSdkTypes.InternalModuleService
+ shippingMethodAdjustmentService: ModulesSdkTypes.InternalModuleService
+ shippingMethodService: ModulesSdkTypes.InternalModuleService
+ lineItemAdjustmentService: ModulesSdkTypes.InternalModuleService
+ lineItemTaxLineService: ModulesSdkTypes.InternalModuleService
+ shippingMethodTaxLineService: ModulesSdkTypes.InternalModuleService
}
-export default class CartModuleService implements ICartModuleService {
+const generateMethodForModels = [
+ Address,
+ LineItem,
+ LineItemAdjustment,
+ LineItemTaxLine,
+ ShippingMethod,
+ ShippingMethodAdjustment,
+ ShippingMethodTaxLine,
+]
+
+export default class CartModuleService<
+ TCart extends Cart = Cart,
+ TAddress extends Address = Address,
+ TLineItem extends LineItem = LineItem,
+ TLineItemAdjustment extends LineItemAdjustment = LineItemAdjustment,
+ TLineItemTaxLine extends LineItemTaxLine = LineItemTaxLine,
+ TShippingMethodAdjustment extends ShippingMethodAdjustment = ShippingMethodAdjustment,
+ TShippingMethodTaxLine extends ShippingMethodTaxLine = ShippingMethodTaxLine,
+ TShippingMethod extends ShippingMethod = ShippingMethod
+ >
+ extends ModulesSdkUtils.abstractModuleServiceFactory<
+ InjectedDependencies,
+ CartTypes.CartDTO,
+ {
+ Address: { dto: CartTypes.CartAddressDTO }
+ LineItem: { dto: CartTypes.CartLineItemDTO }
+ LineItemAdjustment: { dto: CartTypes.LineItemAdjustmentDTO }
+ LineItemTaxLine: { dto: CartTypes.LineItemTaxLineDTO }
+ ShippingMethod: { dto: CartTypes.CartShippingMethodDTO }
+ ShippingMethodAdjustment: { dto: CartTypes.ShippingMethodAdjustmentDTO }
+ ShippingMethodTaxLine: { dto: CartTypes.ShippingMethodTaxLineDTO }
+ }
+ >(Cart, generateMethodForModels, entityNameToLinkableKeysMap)
+ implements ICartModuleService
+{
protected baseRepository_: DAL.RepositoryService
- protected cartService_: services.CartService
- protected addressService_: services.AddressService
- protected lineItemService_: services.LineItemService
- protected shippingMethodAdjustmentService_: services.ShippingMethodAdjustmentService
- protected shippingMethodService_: services.ShippingMethodService
- protected lineItemAdjustmentService_: services.LineItemAdjustmentService
- protected lineItemTaxLineService_: services.LineItemTaxLineService
- protected shippingMethodTaxLineService_: services.ShippingMethodTaxLineService
+ protected cartService_: ModulesSdkTypes.InternalModuleService
+ protected addressService_: ModulesSdkTypes.InternalModuleService
+ protected lineItemService_: ModulesSdkTypes.InternalModuleService
+ protected shippingMethodAdjustmentService_: ModulesSdkTypes.InternalModuleService
+ protected shippingMethodService_: ModulesSdkTypes.InternalModuleService
+ protected lineItemAdjustmentService_: ModulesSdkTypes.InternalModuleService
+ protected lineItemTaxLineService_: ModulesSdkTypes.InternalModuleService
+ protected shippingMethodTaxLineService_: ModulesSdkTypes.InternalModuleService
constructor(
{
@@ -66,6 +109,9 @@ export default class CartModuleService implements ICartModuleService {
}: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
+ // @ts-ignore
+ super(...arguments)
+
this.baseRepository_ = baseRepository
this.cartService_ = cartService
this.addressService_ = addressService
@@ -81,52 +127,6 @@ export default class CartModuleService implements ICartModuleService {
return joinerConfig
}
- @InjectManager("baseRepository_")
- async retrieve(
- id: string,
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const cart = await this.cartService_.retrieve(id, config, sharedContext)
-
- return await this.baseRepository_.serialize(cart, {
- populate: true,
- })
- }
-
- @InjectManager("baseRepository_")
- async list(
- filters: CartTypes.FilterableCartProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const carts = await this.cartService_.list(filters, config, sharedContext)
-
- return this.baseRepository_.serialize(carts, {
- populate: true,
- })
- }
-
- @InjectManager("baseRepository_")
- async listAndCount(
- filters: CartTypes.FilterableCartProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise<[CartTypes.CartDTO[], number]> {
- const [carts, count] = await this.cartService_.listAndCount(
- filters,
- config,
- sharedContext
- )
-
- return [
- await this.baseRepository_.serialize(carts, {
- populate: true,
- }),
- count,
- ]
- }
-
async create(
data: CartTypes.CreateCartDTO[],
sharedContext?: Context
@@ -229,98 +229,6 @@ export default class CartModuleService implements ICartModuleService {
return await this.cartService_.update(data, sharedContext)
}
- async delete(ids: string[], sharedContext?: Context): Promise
-
- async delete(ids: string, sharedContext?: Context): Promise
-
- @InjectTransactionManager("baseRepository_")
- async delete(
- ids: string[] | string,
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const cartIds = Array.isArray(ids) ? ids : [ids]
- await this.cartService_.delete(cartIds, sharedContext)
- }
-
- @InjectManager("baseRepository_")
- async listAddresses(
- filters: CartTypes.FilterableAddressProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const addresses = await this.addressService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize(
- addresses,
- {
- populate: true,
- }
- )
- }
-
- @InjectManager("baseRepository_")
- async retrieveLineItem(
- itemId: string,
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const item = await this.lineItemService_.retrieve(
- itemId,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize(
- item,
- {
- populate: true,
- }
- )
- }
-
- @InjectManager("baseRepository_")
- async listLineItems(
- filters: CartTypes.FilterableLineItemProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const items = await this.lineItemService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize(
- items,
- {
- populate: true,
- }
- )
- }
-
- @InjectManager("baseRepository_")
- async listShippingMethods(
- filters: CartTypes.FilterableShippingMethodProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const methods = await this.shippingMethodService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize<
- CartTypes.CartShippingMethodDTO[]
- >(methods, {
- populate: true,
- })
- }
-
addLineItems(
data: CartTypes.CreateLineItemForCartDTO
): Promise
@@ -585,18 +493,6 @@ export default class CartModuleService implements ICartModuleService {
return await this.addressService_.update(data, sharedContext)
}
- async deleteAddresses(ids: string[], sharedContext?: Context): Promise
- async deleteAddresses(ids: string, sharedContext?: Context): Promise
-
- @InjectTransactionManager("baseRepository_")
- async deleteAddresses(
- ids: string[] | string,
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const addressIds = Array.isArray(ids) ? ids : [ids]
- await this.addressService_.delete(addressIds, sharedContext)
- }
-
async addShippingMethods(
data: CartTypes.CreateShippingMethodDTO
): Promise
@@ -665,7 +561,10 @@ export default class CartModuleService implements ICartModuleService {
data: CartTypes.CreateShippingMethodDTO[],
@MedusaContext() sharedContext: Context = {}
): Promise {
- return await this.shippingMethodService_.create(data, sharedContext)
+ return await this.shippingMethodService_.create(
+ data as unknown as CreateShippingMethodDTO[],
+ sharedContext
+ )
}
async removeShippingMethods(
@@ -708,25 +607,6 @@ export default class CartModuleService implements ICartModuleService {
await this.shippingMethodService_.delete(toDelete, sharedContext)
}
- @InjectManager("baseRepository_")
- async listLineItemAdjustments(
- filters: CartTypes.FilterableLineItemAdjustmentProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const adjustments = await this.lineItemAdjustmentService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize<
- CartTypes.LineItemAdjustmentDTO[]
- >(adjustments, {
- populate: true,
- })
- }
-
async addLineItemAdjustments(
adjustments: CartTypes.CreateLineItemAdjustmentDTO[]
): Promise
@@ -882,25 +762,6 @@ export default class CartModuleService implements ICartModuleService {
await this.lineItemAdjustmentService_.delete(ids, sharedContext)
}
- @InjectManager("baseRepository_")
- async listShippingMethodAdjustments(
- filters: CartTypes.FilterableShippingMethodAdjustmentProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const adjustments = await this.shippingMethodAdjustmentService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize<
- CartTypes.ShippingMethodAdjustmentDTO[]
- >(adjustments, {
- populate: true,
- })
- }
-
@InjectTransactionManager("baseRepository_")
async setShippingMethodAdjustments(
cartId: string,
@@ -1070,26 +931,6 @@ export default class CartModuleService implements ICartModuleService {
await this.shippingMethodAdjustmentService_.delete(ids, sharedContext)
}
- @InjectManager("baseRepository_")
- async listLineItemTaxLines(
- filters: CartTypes.FilterableLineItemTaxLineProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const taxLines = await this.lineItemTaxLineService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize(
- taxLines,
- {
- populate: true,
- }
- )
- }
-
addLineItemTaxLines(
taxLines: CartTypes.CreateLineItemTaxLineDTO[]
): Promise
@@ -1123,14 +964,14 @@ export default class CartModuleService implements ICartModuleService {
const lines = Array.isArray(taxLines) ? taxLines : [taxLines]
addedTaxLines = await this.lineItemTaxLineService_.create(
- lines as CartTypes.CreateLineItemTaxLineDTO[],
+ lines as CreateLineItemTaxLineDTO[],
sharedContext
)
} else {
const data = Array.isArray(cartIdOrData) ? cartIdOrData : [cartIdOrData]
addedTaxLines = await this.lineItemTaxLineService_.create(
- data as CartTypes.CreateLineItemTaxLineDTO[],
+ data as CreateLineItemTaxLineDTO[],
sharedContext
)
}
@@ -1184,13 +1025,15 @@ export default class CartModuleService implements ICartModuleService {
}
})
- await this.lineItemTaxLineService_.delete(
- toDelete.map((taxLine) => taxLine!.id),
- sharedContext
- )
+ if (toDelete.length) {
+ await this.lineItemTaxLineService_.delete(
+ toDelete.map((taxLine) => taxLine!.id),
+ sharedContext
+ )
+ }
const result = await this.lineItemTaxLineService_.upsert(
- taxLines,
+ taxLines as UpdateLineItemTaxLineDTO[],
sharedContext
)
@@ -1242,25 +1085,6 @@ export default class CartModuleService implements ICartModuleService {
await this.lineItemTaxLineService_.delete(ids, sharedContext)
}
- @InjectManager("baseRepository_")
- async listShippingMethodTaxLines(
- filters: CartTypes.FilterableShippingMethodTaxLineProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const taxLines = await this.shippingMethodTaxLineService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize<
- CartTypes.ShippingMethodTaxLineDTO[]
- >(taxLines, {
- populate: true,
- })
- }
-
addShippingMethodTaxLines(
taxLines: CartTypes.CreateShippingMethodTaxLineDTO[]
): Promise
@@ -1296,12 +1120,12 @@ export default class CartModuleService implements ICartModuleService {
const lines = Array.isArray(taxLines) ? taxLines : [taxLines]
addedTaxLines = await this.shippingMethodTaxLineService_.create(
- lines as CartTypes.CreateShippingMethodTaxLineDTO[],
+ lines as CreateShippingMethodTaxLineDTO[],
sharedContext
)
} else {
addedTaxLines = await this.shippingMethodTaxLineService_.create(
- taxLines as CartTypes.CreateShippingMethodTaxLineDTO[],
+ taxLines as CreateShippingMethodTaxLineDTO[],
sharedContext
)
}
@@ -1367,7 +1191,7 @@ export default class CartModuleService implements ICartModuleService {
}
const result = await this.shippingMethodTaxLineService_.upsert(
- taxLines,
+ taxLines as UpdateShippingMethodTaxLineDTO[],
sharedContext
)
diff --git a/packages/cart/src/services/cart.ts b/packages/cart/src/services/cart.ts
deleted file mode 100644
index a9c594555b1ca..0000000000000
--- a/packages/cart/src/services/cart.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { DAL } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { Cart } from "@models"
-import { CreateCartDTO, UpdateCartDTO } from "@types"
-
-type InjectedDependencies = {
- cartRepository: DAL.RepositoryService
-}
-
-export default class CartService<
- TEntity extends Cart = Cart
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CreateCartDTO
- update: UpdateCartDTO
- }
->(Cart) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/cart/src/services/index.ts b/packages/cart/src/services/index.ts
index 7120b701d7fee..2ed2053ffcb36 100644
--- a/packages/cart/src/services/index.ts
+++ b/packages/cart/src/services/index.ts
@@ -1,10 +1 @@
-export { default as AddressService } from "./address"
-export { default as CartService } from "./cart"
export { default as CartModuleService } from "./cart-module"
-export { default as LineItemService } from "./line-item"
-export { default as LineItemAdjustmentService } from "./line-item-adjustment"
-export { default as LineItemTaxLineService } from "./line-item-tax-line"
-export { default as ShippingMethodService } from "./shipping-method"
-export { default as ShippingMethodAdjustmentService } from "./shipping-method-adjustment"
-export { default as ShippingMethodTaxLineService } from "./shipping-method-tax-line"
-
diff --git a/packages/cart/src/services/line-item-adjustment.ts b/packages/cart/src/services/line-item-adjustment.ts
deleted file mode 100644
index 9ee93b2d95820..0000000000000
--- a/packages/cart/src/services/line-item-adjustment.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { DAL } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { LineItemAdjustment } from "@models"
-import {
- CreateLineItemAdjustmentDTO,
- UpdateLineItemAdjustmentDTO,
-} from "@types"
-
-type InjectedDependencies = {
- lineItemAdjustmentRepository: DAL.RepositoryService
-}
-
-export default class LineItemAdjustmentService<
- TEntity extends LineItemAdjustment = LineItemAdjustment
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CreateLineItemAdjustmentDTO
- update: UpdateLineItemAdjustmentDTO
- }
->(LineItemAdjustment) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/cart/src/services/line-item-tax-line.ts b/packages/cart/src/services/line-item-tax-line.ts
deleted file mode 100644
index a740fae4366d1..0000000000000
--- a/packages/cart/src/services/line-item-tax-line.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import {
- CreateLineItemTaxLineDTO,
- DAL,
- UpdateLineItemTaxLineDTO,
-} from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { LineItemTaxLine } from "@models"
-
-type InjectedDependencies = {
- lineItemTaxLineRepository: DAL.RepositoryService
-}
-
-export default class LineItemTaxLineService<
- TEntity extends LineItemTaxLine = LineItemTaxLine
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CreateLineItemTaxLineDTO
- update: UpdateLineItemTaxLineDTO
- }
->(LineItemTaxLine) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/cart/src/services/line-item.ts b/packages/cart/src/services/line-item.ts
deleted file mode 100644
index ec736f4010249..0000000000000
--- a/packages/cart/src/services/line-item.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { DAL } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { LineItem } from "@models"
-import { CreateLineItemDTO, UpdateLineItemDTO } from "@types"
-
-type InjectedDependencies = {
- lineItemRepository: DAL.RepositoryService
-}
-
-export default class LineItemService<
- TEntity extends LineItem = LineItem
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CreateLineItemDTO
- update: UpdateLineItemDTO
- }
->(LineItem) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/cart/src/services/shipping-method-adjustment.ts b/packages/cart/src/services/shipping-method-adjustment.ts
deleted file mode 100644
index 5688cd662babe..0000000000000
--- a/packages/cart/src/services/shipping-method-adjustment.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { DAL } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { ShippingMethodAdjustment } from "@models"
-import {
- CreateShippingMethodAdjustmentDTO,
- UpdateShippingMethodAdjustmentDTO,
-} from "@types"
-
-type InjectedDependencies = {
- shippingMethodAdjustmentRepository: DAL.RepositoryService
-}
-
-export default class ShippingMethodAdjustmentService<
- TEntity extends ShippingMethodAdjustment = ShippingMethodAdjustment
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CreateShippingMethodAdjustmentDTO
- update: UpdateShippingMethodAdjustmentDTO
- }
->(ShippingMethodAdjustment) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/cart/src/services/shipping-method-tax-line.ts b/packages/cart/src/services/shipping-method-tax-line.ts
deleted file mode 100644
index 9229d6556717b..0000000000000
--- a/packages/cart/src/services/shipping-method-tax-line.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { CreateShippingMethodTaxLineDTO, DAL, UpdateShippingMethodTaxLineDTO } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { ShippingMethodTaxLine } from "@models"
-
-type InjectedDependencies = {
- shippingMethodTaxLineRepository: DAL.RepositoryService
-}
-
-export default class ShippingMethodTaxLineService<
- TEntity extends ShippingMethodTaxLine = ShippingMethodTaxLine
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CreateShippingMethodTaxLineDTO
- update: UpdateShippingMethodTaxLineDTO
- }
->(ShippingMethodTaxLine) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/cart/src/services/shipping-method.ts b/packages/cart/src/services/shipping-method.ts
deleted file mode 100644
index f3cf6671442ee..0000000000000
--- a/packages/cart/src/services/shipping-method.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { DAL } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { ShippingMethod } from "@models"
-import { CreateShippingMethodDTO, UpdateShippingMethodDTO } from "../types"
-
-type InjectedDependencies = {
- shippingMethodRepository: DAL.RepositoryService
-}
-
-export default class ShippingMethodService<
- TEntity extends ShippingMethod = ShippingMethod
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CreateShippingMethodDTO
- update: UpdateShippingMethodDTO
- }
->(ShippingMethod) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/cart/src/types/index.ts b/packages/cart/src/types/index.ts
index 03f39f0916b24..9e420fcb7f908 100644
--- a/packages/cart/src/types/index.ts
+++ b/packages/cart/src/types/index.ts
@@ -5,7 +5,6 @@ export * from "./cart"
export * from "./line-item"
export * from "./line-item-adjustment"
export * from "./line-item-tax-line"
-export * from "./repositories"
export * from "./shipping-method"
export * from "./shipping-method-adjustment"
export * from "./shipping-method-tax-line"
diff --git a/packages/cart/src/types/repositories.ts b/packages/cart/src/types/repositories.ts
deleted file mode 100644
index 3d028f6c8e20a..0000000000000
--- a/packages/cart/src/types/repositories.ts
+++ /dev/null
@@ -1,114 +0,0 @@
-import { DAL } from "@medusajs/types"
-import {
- Cart,
- LineItem,
- LineItemAdjustment,
- LineItemTaxLine,
- ShippingMethod,
- ShippingMethodAdjustment,
- ShippingMethodTaxLine,
-} from "@models"
-import { CreateAddressDTO, UpdateAddressDTO } from "./address"
-import { CreateCartDTO, UpdateCartDTO } from "./cart"
-import { CreateLineItemDTO, UpdateLineItemDTO } from "./line-item"
-import {
- CreateLineItemAdjustmentDTO,
- UpdateLineItemAdjustmentDTO,
-} from "./line-item-adjustment"
-import {
- CreateLineItemTaxLineDTO,
- UpdateLineItemTaxLineDTO,
-} from "./line-item-tax-line"
-import {
- CreateShippingMethodDTO,
- UpdateShippingMethodDTO,
-} from "./shipping-method"
-import {
- CreateShippingMethodAdjustmentDTO,
- UpdateShippingMethodAdjustmentDTO,
-} from "./shipping-method-adjustment"
-import {
- CreateShippingMethodTaxLineDTO,
- UpdateShippingMethodTaxLineDTO,
-} from "./shipping-method-tax-line"
-
-// eslint-disable-next-line @typescript-eslint/no-empty-interface
-export interface IAddressRepository
- extends DAL.RepositoryService<
- TEntity,
- {
- create: CreateAddressDTO
- update: UpdateAddressDTO
- }
- > {}
-
-// eslint-disable-next-line @typescript-eslint/no-empty-interface
-export interface ICartRepository
- extends DAL.RepositoryService<
- TEntity,
- {
- create: CreateCartDTO
- update: UpdateCartDTO
- }
- > {}
-
-// eslint-disable-next-line @typescript-eslint/no-empty-interface
-export interface ILineItemRepository
- extends DAL.RepositoryService<
- TEntity,
- {
- create: CreateLineItemDTO
- update: UpdateLineItemDTO
- }
- > {}
-
-// eslint-disable-next-line @typescript-eslint/no-empty-interface
-export interface IShippingMethodRepository<
- TEntity extends ShippingMethod = ShippingMethod
-> extends DAL.RepositoryService<
- TEntity,
- {
- create: CreateShippingMethodDTO
- update: UpdateShippingMethodDTO
- }
- > {}
-
-export interface ILineItemAdjustmentRepository<
- TEntity extends LineItemAdjustment = LineItemAdjustment
-> extends DAL.RepositoryService<
- TEntity,
- {
- create: CreateLineItemAdjustmentDTO
- update: UpdateLineItemAdjustmentDTO
- }
- > {}
-
-export interface IShippingMethodAdjustmentRepository<
- TEntity extends ShippingMethodAdjustment = ShippingMethodAdjustment
-> extends DAL.RepositoryService<
- TEntity,
- {
- create: CreateShippingMethodAdjustmentDTO
- update: UpdateShippingMethodAdjustmentDTO
- }
- > {}
-
-export interface IShippingMethodTaxLineRepository<
- TEntity extends ShippingMethodTaxLine = ShippingMethodTaxLine
-> extends DAL.RepositoryService<
- TEntity,
- {
- create: CreateShippingMethodTaxLineDTO
- update: UpdateShippingMethodTaxLineDTO
- }
- > {}
-
-export interface ILineItemTaxLineRepository<
- TEntity extends LineItemTaxLine = LineItemTaxLine
-> extends DAL.RepositoryService<
- TEntity,
- {
- create: CreateLineItemTaxLineDTO
- update: UpdateLineItemTaxLineDTO
- }
- > {}
diff --git a/packages/cart/src/types/shipping-method.ts b/packages/cart/src/types/shipping-method.ts
index 6e70a4056bc0c..6d15473f1b6ea 100644
--- a/packages/cart/src/types/shipping-method.ts
+++ b/packages/cart/src/types/shipping-method.ts
@@ -1,6 +1,6 @@
export interface CreateShippingMethodDTO {
name: string
- cart_id: string
+ shippingMethod_id: string
amount: number
data?: Record
}
diff --git a/packages/core-flows/src/customer-group/steps/delete-customer-groups.ts b/packages/core-flows/src/customer-group/steps/delete-customer-groups.ts
index b2b074842c701..d9ad730678c8a 100644
--- a/packages/core-flows/src/customer-group/steps/delete-customer-groups.ts
+++ b/packages/core-flows/src/customer-group/steps/delete-customer-groups.ts
@@ -12,7 +12,7 @@ export const deleteCustomerGroupStep = createStep(
ModuleRegistrationName.CUSTOMER
)
- await service.softDeleteCustomerGroup(ids)
+ await service.softDeleteCustomerGroups(ids)
return new StepResponse(void 0, ids)
},
@@ -25,6 +25,6 @@ export const deleteCustomerGroupStep = createStep(
ModuleRegistrationName.CUSTOMER
)
- await service.restoreCustomerGroup(prevCustomerGroups)
+ await service.restoreCustomerGroups(prevCustomerGroups)
}
)
diff --git a/packages/core-flows/src/customer-group/steps/update-customer-groups.ts b/packages/core-flows/src/customer-group/steps/update-customer-groups.ts
index 553f1d5ae6c09..7acced28ebe40 100644
--- a/packages/core-flows/src/customer-group/steps/update-customer-groups.ts
+++ b/packages/core-flows/src/customer-group/steps/update-customer-groups.ts
@@ -1,8 +1,8 @@
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import {
+ CustomerGroupUpdatableFields,
FilterableCustomerGroupProps,
ICustomerModuleService,
- CustomerGroupUpdatableFields,
} from "@medusajs/types"
import {
getSelectsAndRelationsFromObjectArray,
@@ -31,7 +31,7 @@ export const updateCustomerGroupsStep = createStep(
relations,
})
- const customers = await service.updateCustomerGroup(
+ const customers = await service.updateCustomerGroups(
data.selector,
data.update
)
@@ -49,7 +49,7 @@ export const updateCustomerGroupsStep = createStep(
await promiseAll(
prevCustomerGroups.map((c) =>
- service.updateCustomerGroup(c.id, {
+ service.updateCustomerGroups(c.id, {
name: c.name,
})
)
diff --git a/packages/core-flows/src/customer/steps/create-addresses.ts b/packages/core-flows/src/customer/steps/create-addresses.ts
index 139aebf0d248a..a14686069d371 100644
--- a/packages/core-flows/src/customer/steps/create-addresses.ts
+++ b/packages/core-flows/src/customer/steps/create-addresses.ts
@@ -1,8 +1,8 @@
import {
- ICustomerModuleService,
CreateCustomerAddressDTO,
+ ICustomerModuleService,
} from "@medusajs/types"
-import { StepResponse, createStep } from "@medusajs/workflows-sdk"
+import { createStep, StepResponse } from "@medusajs/workflows-sdk"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export const createCustomerAddressesStepId = "create-customer-addresses"
@@ -29,6 +29,6 @@ export const createCustomerAddressesStep = createStep(
ModuleRegistrationName.CUSTOMER
)
- await service.deleteAddress(ids)
+ await service.deleteAddresses(ids)
}
)
diff --git a/packages/core-flows/src/customer/steps/delete-addresses.ts b/packages/core-flows/src/customer/steps/delete-addresses.ts
index c6ed1732993ac..46bfcab654cf7 100644
--- a/packages/core-flows/src/customer/steps/delete-addresses.ts
+++ b/packages/core-flows/src/customer/steps/delete-addresses.ts
@@ -14,7 +14,7 @@ export const deleteCustomerAddressesStep = createStep(
const existing = await service.listAddresses({
id: ids,
})
- await service.deleteAddress(ids)
+ await service.deleteAddresses(ids)
return new StepResponse(void 0, existing)
},
diff --git a/packages/core-flows/src/customer/steps/maybe-unset-default-billing-addresses.ts b/packages/core-flows/src/customer/steps/maybe-unset-default-billing-addresses.ts
index 50a2b36aca19d..70212f2c51482 100644
--- a/packages/core-flows/src/customer/steps/maybe-unset-default-billing-addresses.ts
+++ b/packages/core-flows/src/customer/steps/maybe-unset-default-billing-addresses.ts
@@ -1,12 +1,12 @@
import {
- ICustomerModuleService,
CreateCustomerAddressDTO,
- FilterableCustomerAddressProps,
CustomerAddressDTO,
+ FilterableCustomerAddressProps,
+ ICustomerModuleService,
} from "@medusajs/types"
import { createStep } from "@medusajs/workflows-sdk"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
-import { unsetForUpdate, unsetForCreate } from "./utils"
+import { unsetForCreate, unsetForUpdate } from "./utils"
import { isDefined } from "@medusajs/utils"
type StepInput = {
@@ -53,7 +53,7 @@ export const maybeUnsetDefaultBillingAddressesStep = createStep(
ModuleRegistrationName.CUSTOMER
)
- await customerModuleService.updateAddress(
+ await customerModuleService.updateAddresses(
{ id: addressesToSet },
{ is_default_billing: true }
)
diff --git a/packages/core-flows/src/customer/steps/maybe-unset-default-shipping-addresses.ts b/packages/core-flows/src/customer/steps/maybe-unset-default-shipping-addresses.ts
index 7ffbaf41b0e16..b484c31a5f089 100644
--- a/packages/core-flows/src/customer/steps/maybe-unset-default-shipping-addresses.ts
+++ b/packages/core-flows/src/customer/steps/maybe-unset-default-shipping-addresses.ts
@@ -1,12 +1,12 @@
import {
- ICustomerModuleService,
CreateCustomerAddressDTO,
- FilterableCustomerAddressProps,
CustomerAddressDTO,
+ FilterableCustomerAddressProps,
+ ICustomerModuleService,
} from "@medusajs/types"
import { createStep } from "@medusajs/workflows-sdk"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
-import { unsetForUpdate, unsetForCreate } from "./utils"
+import { unsetForCreate, unsetForUpdate } from "./utils"
import { isDefined } from "@medusajs/utils"
type StepInput = {
@@ -52,7 +52,7 @@ export const maybeUnsetDefaultShippingAddressesStep = createStep(
ModuleRegistrationName.CUSTOMER
)
- await customerModuleService.updateAddress(
+ await customerModuleService.updateAddresses(
{ id: addressesToSet },
{ is_default_shipping: true }
)
diff --git a/packages/core-flows/src/customer/steps/update-addresses.ts b/packages/core-flows/src/customer/steps/update-addresses.ts
index 17d7d68be1901..49b793e36b09b 100644
--- a/packages/core-flows/src/customer/steps/update-addresses.ts
+++ b/packages/core-flows/src/customer/steps/update-addresses.ts
@@ -31,7 +31,7 @@ export const updateCustomerAddressesStep = createStep(
relations,
})
- const customerAddresses = await service.updateAddress(
+ const customerAddresses = await service.updateAddresses(
data.selector,
data.update
)
@@ -48,7 +48,7 @@ export const updateCustomerAddressesStep = createStep(
)
await promiseAll(
- prevCustomerAddresses.map((c) => service.updateAddress(c.id, { ...c }))
+ prevCustomerAddresses.map((c) => service.updateAddresses(c.id, { ...c }))
)
}
)
diff --git a/packages/core-flows/src/customer/steps/utils/unset-address-for-create.ts b/packages/core-flows/src/customer/steps/utils/unset-address-for-create.ts
index 25c6e15df2479..870e67a7a416b 100644
--- a/packages/core-flows/src/customer/steps/utils/unset-address-for-create.ts
+++ b/packages/core-flows/src/customer/steps/utils/unset-address-for-create.ts
@@ -21,7 +21,7 @@ export const unsetForCreate = async (
[field]: true,
})
- await customerService.updateAddress(
+ await customerService.updateAddresses(
{ customer_id: customerIds, [field]: true },
{ [field]: false }
)
diff --git a/packages/core-flows/src/customer/steps/utils/unset-address-for-update.ts b/packages/core-flows/src/customer/steps/utils/unset-address-for-update.ts
index aa12bb2122f2b..404b550a9cf5a 100644
--- a/packages/core-flows/src/customer/steps/utils/unset-address-for-update.ts
+++ b/packages/core-flows/src/customer/steps/utils/unset-address-for-update.ts
@@ -28,7 +28,7 @@ export const unsetForUpdate = async (
[field]: true,
})
- await customerService.updateAddress(
+ await customerService.updateAddresses(
{ customer_id: customerIds, [field]: true },
{ [field]: false }
)
diff --git a/packages/customer/integration-tests/__tests__/services/customer-module/index.spec.ts b/packages/customer/integration-tests/__tests__/services/customer-module/index.spec.ts
index 26beb2c4abf66..ae5236c734d76 100644
--- a/packages/customer/integration-tests/__tests__/services/customer-module/index.spec.ts
+++ b/packages/customer/integration-tests/__tests__/services/customer-module/index.spec.ts
@@ -535,7 +535,7 @@ describe("Customer Module Service", () => {
await service.delete(customer.id)
- const res = await service.listCustomerGroupRelations({
+ const res = await service.listCustomerGroupCustomers({
customer_id: customer.id,
customer_group_id: group.id,
})
@@ -546,7 +546,7 @@ describe("Customer Module Service", () => {
describe("deleteCustomerGroup", () => {
it("should delete a single customer group", async () => {
const [group] = await service.createCustomerGroup([{ name: "VIP" }])
- await service.deleteCustomerGroup(group.id)
+ await service.deleteCustomerGroups(group.id)
await expect(
service.retrieveCustomerGroup(group.id)
@@ -560,7 +560,7 @@ describe("Customer Module Service", () => {
])
const groupIds = groups.map((group) => group.id)
- await service.deleteCustomerGroup(groupIds)
+ await service.deleteCustomerGroups(groupIds)
for (const group of groups) {
await expect(
@@ -575,7 +575,7 @@ describe("Customer Module Service", () => {
await service.createCustomerGroup([{ name: "VIP" }, { name: "Regular" }])
const selector = { name: "VIP" }
- await service.deleteCustomerGroup(selector)
+ await service.deleteCustomerGroups(selector)
const remainingGroups = await service.listCustomerGroups({ name: "VIP" })
expect(remainingGroups.length).toBe(0)
@@ -595,9 +595,9 @@ describe("Customer Module Service", () => {
customer_group_id: group.id,
})
- await service.deleteCustomerGroup(group.id)
+ await service.deleteCustomerGroups(group.id)
- const res = await service.listCustomerGroupRelations({
+ const res = await service.listCustomerGroupCustomers({
customer_id: customer.id,
customer_group_id: group.id,
})
@@ -743,7 +743,7 @@ describe("Customer Module Service", () => {
address_1: "123 Main St",
})
- await service.updateAddress(address.id, {
+ await service.updateAddresses(address.id, {
address_name: "Work",
address_1: "456 Main St",
})
@@ -778,7 +778,7 @@ describe("Customer Module Service", () => {
address_1: "456 Main St",
})
- await service.updateAddress(
+ await service.updateAddresses(
{ customer_id: customer.id },
{
address_name: "Under Construction",
@@ -822,7 +822,7 @@ describe("Customer Module Service", () => {
},
])
- await service.updateAddress([address1.id, address2.id], {
+ await service.updateAddresses([address1.id, address2.id], {
address_name: "Under Construction",
})
@@ -864,7 +864,7 @@ describe("Customer Module Service", () => {
})
await expect(
- service.updateAddress(address.id, { is_default_shipping: true })
+ service.updateAddresses(address.id, { is_default_shipping: true })
).rejects.toThrow("A default shipping address already exists")
})
})
@@ -1087,7 +1087,7 @@ describe("Customer Module Service", () => {
describe("softDeleteCustomerGroup", () => {
it("should soft delete a single customer group", async () => {
const [group] = await service.createCustomerGroup([{ name: "VIP" }])
- await service.softDeleteCustomerGroup([group.id])
+ await service.softDeleteCustomerGroups([group.id])
const res = await service.listCustomerGroups({ id: group.id })
expect(res.length).toBe(0)
@@ -1105,7 +1105,7 @@ describe("Customer Module Service", () => {
{ name: "Regular" },
])
const groupIds = groups.map((group) => group.id)
- await service.softDeleteCustomerGroup(groupIds)
+ await service.softDeleteCustomerGroups(groupIds)
const res = await service.listCustomerGroups({ id: groupIds })
expect(res.length).toBe(0)
@@ -1121,12 +1121,12 @@ describe("Customer Module Service", () => {
describe("restoreCustomerGroup", () => {
it("should restore a single customer group", async () => {
const [group] = await service.createCustomerGroup([{ name: "VIP" }])
- await service.softDeleteCustomerGroup([group.id])
+ await service.softDeleteCustomerGroups([group.id])
const res = await service.listCustomerGroups({ id: group.id })
expect(res.length).toBe(0)
- await service.restoreCustomerGroup([group.id])
+ await service.restoreCustomerGroups([group.id])
const restoredGroup = await service.retrieveCustomerGroup(group.id, {
withDeleted: true,
@@ -1140,12 +1140,12 @@ describe("Customer Module Service", () => {
{ name: "Regular" },
])
const groupIds = groups.map((group) => group.id)
- await service.softDeleteCustomerGroup(groupIds)
+ await service.softDeleteCustomerGroups(groupIds)
const res = await service.listCustomerGroups({ id: groupIds })
expect(res.length).toBe(0)
- await service.restoreCustomerGroup(groupIds)
+ await service.restoreCustomerGroups(groupIds)
const restoredGroups = await service.listCustomerGroups(
{ id: groupIds },
diff --git a/packages/customer/package.json b/packages/customer/package.json
index 6f58a6cf6c197..637c791163066 100644
--- a/packages/customer/package.json
+++ b/packages/customer/package.json
@@ -55,7 +55,7 @@
"@mikro-orm/migrations": "5.9.7",
"@mikro-orm/postgresql": "5.9.7",
"awilix": "^8.0.0",
- "dotenv": "^16.1.4",
+ "dotenv": "16.3.1",
"knex": "2.4.2"
}
}
diff --git a/packages/customer/src/models/address.ts b/packages/customer/src/models/address.ts
index 13aacd7c005a5..817d4c2771cc4 100644
--- a/packages/customer/src/models/address.ts
+++ b/packages/customer/src/models/address.ts
@@ -2,27 +2,32 @@ import { DAL } from "@medusajs/types"
import { generateEntityId } from "@medusajs/utils"
import {
BeforeCreate,
+ Cascade,
Entity,
+ Index,
+ ManyToOne,
OnInit,
OptionalProps,
PrimaryKey,
Property,
- ManyToOne,
- Cascade,
- Index,
} from "@mikro-orm/core"
import Customer from "./customer"
type OptionalAddressProps = DAL.EntityDateColumns // TODO: To be revisited when more clear
+export const UNIQUE_CUSTOMER_SHIPPING_ADDRESS =
+ "IDX_customer_address_unique_customer_shipping"
+export const UNIQUE_CUSTOMER_BILLING_ADDRESS =
+ "IDX_customer_address_unique_customer_billing"
+
@Entity({ tableName: "customer_address" })
@Index({
- name: "IDX_customer_address_unique_customer_shipping",
+ name: UNIQUE_CUSTOMER_SHIPPING_ADDRESS,
expression:
'create unique index "IDX_customer_address_unique_customer_shipping" on "customer_address" ("customer_id") where "is_default_shipping" = true',
})
@Index({
- name: "IDX_customer_address_unique_customer_billing",
+ name: UNIQUE_CUSTOMER_BILLING_ADDRESS,
expression:
'create unique index "IDX_customer_address_unique_customer_billing" on "customer_address" ("customer_id") where "is_default_billing" = true',
})
diff --git a/packages/customer/src/services/address.ts b/packages/customer/src/services/address.ts
deleted file mode 100644
index 383a07707bc37..0000000000000
--- a/packages/customer/src/services/address.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { DAL } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { Address } from "@models"
-import { CreateAddressDTO, UpdateAddressDTO } from "@types"
-
-type InjectedDependencies = {
- addressRepository: DAL.RepositoryService
-}
-
-export default class AddressService<
- TEntity extends Address = Address
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CreateAddressDTO
- update: UpdateAddressDTO
- }
->(Address) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/customer/src/services/customer-group-customer.ts b/packages/customer/src/services/customer-group-customer.ts
deleted file mode 100644
index cc61f576af834..0000000000000
--- a/packages/customer/src/services/customer-group-customer.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { DAL } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { CustomerGroupCustomer } from "@models"
-
-type CreateCustomerGroupCustomerDTO = {
- customer_id: string
- customer_group_id: string
- created_by?: string
-}
-
-type InjectedDependencies = {
- customerGroupRepository: DAL.RepositoryService
-}
-
-export default class CustomerGroupCustomerService<
- TEntity extends CustomerGroupCustomer = CustomerGroupCustomer
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- { create: CreateCustomerGroupCustomerDTO }
->(CustomerGroupCustomer) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/customer/src/services/customer-group.ts b/packages/customer/src/services/customer-group.ts
deleted file mode 100644
index 830e949c58ddb..0000000000000
--- a/packages/customer/src/services/customer-group.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { DAL } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { CustomerGroup } from "@models"
-import { CreateCustomerGroupDTO, UpdateCustomerGroupDTO } from "@medusajs/types"
-
-type InjectedDependencies = {
- customerGroupRepository: DAL.RepositoryService
-}
-
-export default class CustomerGroupService<
- TEntity extends CustomerGroup = CustomerGroup
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CreateCustomerGroupDTO
- update: UpdateCustomerGroupDTO
- }
->(CustomerGroup) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/customer/src/services/customer-module.ts b/packages/customer/src/services/customer-module.ts
index 7a41d481b84f9..49b6422e80a94 100644
--- a/packages/customer/src/services/customer-module.ts
+++ b/packages/customer/src/services/customer-module.ts
@@ -1,48 +1,69 @@
import {
Context,
+ CustomerDTO,
+ CustomerTypes,
DAL,
- FindConfig,
ICustomerModuleService,
InternalModuleDeclaration,
ModuleJoinerConfig,
- CustomerTypes,
- SoftDeleteReturn,
- RestoreReturn,
+ ModulesSdkTypes,
} from "@medusajs/types"
import {
InjectManager,
InjectTransactionManager,
- MedusaContext,
- mapObjectTo,
- isString,
- isObject,
isDuplicateError,
+ isString,
+ MedusaContext,
+ MedusaError,
+ ModulesSdkUtils,
} from "@medusajs/utils"
import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
-import * as services from "../services"
-import { MedusaError } from "@medusajs/utils"
+import {
+ Address,
+ Customer,
+ CustomerGroup,
+ CustomerGroupCustomer,
+} from "@models"
import { EntityManager } from "@mikro-orm/core"
-
-const UNIQUE_CUSTOMER_SHIPPING_ADDRESS =
- "IDX_customer_address_unique_customer_shipping"
-const UNIQUE_CUSTOMER_BILLING_ADDRESS =
- "IDX_customer_address_unique_customer_billing"
+import {
+ UNIQUE_CUSTOMER_BILLING_ADDRESS,
+ UNIQUE_CUSTOMER_SHIPPING_ADDRESS,
+} from "../models/address"
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
- customerService: services.CustomerService
- addressService: services.AddressService
- customerGroupService: services.CustomerGroupService
- customerGroupCustomerService: services.CustomerGroupCustomerService
+ customerService: ModulesSdkTypes.InternalModuleService
+ addressService: ModulesSdkTypes.InternalModuleService
+ customerGroupService: ModulesSdkTypes.InternalModuleService
+ customerGroupCustomerService: ModulesSdkTypes.InternalModuleService
}
-export default class CustomerModuleService implements ICustomerModuleService {
+const generateMethodForModels = [Address, CustomerGroup, CustomerGroupCustomer]
+
+export default class CustomerModuleService<
+ TAddress extends Address = Address,
+ TCustomer extends Customer = Customer,
+ TCustomerGroup extends CustomerGroup = CustomerGroup,
+ TCustomerGroupCustomer extends CustomerGroupCustomer = CustomerGroupCustomer
+ >
+ // TODO seb I let you manage that when you are moving forward
+ extends ModulesSdkUtils.abstractModuleServiceFactory<
+ InjectedDependencies,
+ CustomerDTO,
+ {
+ Address: { dto: any }
+ CustomerGroup: { dto: any }
+ CustomerGroupCustomer: { dto: any }
+ }
+ >(Customer, generateMethodForModels, entityNameToLinkableKeysMap)
+ implements ICustomerModuleService
+{
protected baseRepository_: DAL.RepositoryService
- protected customerService_: services.CustomerService
- protected addressService_: services.AddressService
- protected customerGroupService_: services.CustomerGroupService
- protected customerGroupCustomerService_: services.CustomerGroupCustomerService
+ protected customerService_: ModulesSdkTypes.InternalModuleService
+ protected addressService_: ModulesSdkTypes.InternalModuleService
+ protected customerGroupService_: ModulesSdkTypes.InternalModuleService
+ protected customerGroupCustomerService_: ModulesSdkTypes.InternalModuleService
constructor(
{
@@ -54,6 +75,9 @@ export default class CustomerModuleService implements ICustomerModuleService {
}: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
+ // @ts-ignore
+ super(...arguments)
+
this.baseRepository_ = baseRepository
this.customerService_ = customerService
this.addressService_ = addressService
@@ -65,26 +89,6 @@ export default class CustomerModuleService implements ICustomerModuleService {
return joinerConfig
}
- @InjectManager("baseRepository_")
- async retrieve(
- id: string,
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const customer = await this.customerService_.retrieve(
- id,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize(
- customer,
- {
- populate: true,
- }
- )
- }
-
async create(
data: CustomerTypes.CreateCustomerDTO,
sharedContext?: Context
@@ -95,13 +99,33 @@ export default class CustomerModuleService implements ICustomerModuleService {
sharedContext?: Context
): Promise
- @InjectTransactionManager("baseRepository_")
+ @InjectManager("baseRepository_")
async create(
dataOrArray:
| CustomerTypes.CreateCustomerDTO
| CustomerTypes.CreateCustomerDTO[],
@MedusaContext() sharedContext: Context = {}
- ) {
+ ): Promise {
+ const customers = await this.create_(dataOrArray, sharedContext).catch(
+ this.handleDbErrors
+ )
+
+ const serialized = await this.baseRepository_.serialize<
+ CustomerTypes.CustomerDTO[]
+ >(customers, {
+ populate: true,
+ })
+
+ return Array.isArray(dataOrArray) ? serialized : serialized[0]
+ }
+
+ @InjectTransactionManager("baseRepository_")
+ async create_(
+ dataOrArray:
+ | CustomerTypes.CreateCustomerDTO
+ | CustomerTypes.CreateCustomerDTO[],
+ @MedusaContext() sharedContext: Context = {}
+ ): Promise {
const data = Array.isArray(dataOrArray) ? dataOrArray : [dataOrArray]
const customers = await this.customerService_.create(data, sharedContext)
@@ -121,12 +145,7 @@ export default class CustomerModuleService implements ICustomerModuleService {
await this.addAddresses(addressDataWithCustomerIds, sharedContext)
- const serialized = await this.baseRepository_.serialize<
- CustomerTypes.CustomerDTO[]
- >(customers, {
- populate: true,
- })
- return Array.isArray(dataOrArray) ? serialized : serialized[0]
+ return customers as unknown as CustomerTypes.CustomerDTO[]
}
update(
@@ -151,37 +170,38 @@ export default class CustomerModuleService implements ICustomerModuleService {
data: CustomerTypes.CustomerUpdatableFields,
@MedusaContext() sharedContext: Context = {}
) {
- let updateData: CustomerTypes.UpdateCustomerDTO[] = []
+ let updateData:
+ | CustomerTypes.UpdateCustomerDTO
+ | CustomerTypes.UpdateCustomerDTO[]
+ | {
+ selector: CustomerTypes.FilterableCustomerProps
+ data: CustomerTypes.CustomerUpdatableFields
+ } = []
+
if (isString(idsOrSelector)) {
- updateData = [
- {
- id: idsOrSelector,
- ...data,
- },
- ]
+ updateData = {
+ id: idsOrSelector,
+ ...data,
+ }
} else if (Array.isArray(idsOrSelector)) {
updateData = idsOrSelector.map((id) => ({
id,
...data,
}))
} else {
- const ids = await this.customerService_.list(
- idsOrSelector,
- { select: ["id"] },
- sharedContext
- )
- updateData = ids.map(({ id }) => ({
- id,
- ...data,
- }))
+ updateData = {
+ selector: idsOrSelector,
+ data: data,
+ }
}
const customers = await this.customerService_.update(
updateData,
sharedContext
)
+
const serialized = await this.baseRepository_.serialize<
- CustomerTypes.CustomerDTO[]
+ CustomerTypes.CustomerDTO | CustomerTypes.CustomerDTO[]
>(customers, {
populate: true,
})
@@ -189,78 +209,6 @@ export default class CustomerModuleService implements ICustomerModuleService {
return isString(idsOrSelector) ? serialized[0] : serialized
}
- delete(customerId: string, sharedContext?: Context): Promise
- delete(customerIds: string[], sharedContext?: Context): Promise
- delete(
- selector: CustomerTypes.FilterableCustomerProps,
- sharedContext?: Context
- ): Promise
-
- @InjectTransactionManager("baseRepository_")
- async delete(
- idsOrSelector: string | string[] | CustomerTypes.FilterableCustomerProps,
- @MedusaContext() sharedContext: Context = {}
- ) {
- let toDelete = Array.isArray(idsOrSelector)
- ? idsOrSelector
- : [idsOrSelector as string]
- if (isObject(idsOrSelector)) {
- const ids = await this.customerService_.list(
- idsOrSelector,
- {
- select: ["id"],
- },
- sharedContext
- )
- toDelete = ids.map(({ id }) => id)
- }
-
- return await this.customerService_.delete(toDelete, sharedContext)
- }
-
- @InjectManager("baseRepository_")
- async list(
- filters: CustomerTypes.FilterableCustomerProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const customers = await this.customerService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize(
- customers,
- {
- populate: true,
- }
- )
- }
-
- @InjectManager("baseRepository_")
- async listAndCount(
- filters: CustomerTypes.FilterableCustomerProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise<[CustomerTypes.CustomerDTO[], number]> {
- const [customers, count] = await this.customerService_.listAndCount(
- filters,
- config,
- sharedContext
- )
-
- return [
- await this.baseRepository_.serialize(
- customers,
- {
- populate: true,
- }
- ),
- count,
- ]
- }
-
async createCustomerGroup(
dataOrArrayOfData: CustomerTypes.CreateCustomerGroupDTO,
sharedContext?: Context
@@ -278,55 +226,36 @@ export default class CustomerModuleService implements ICustomerModuleService {
| CustomerTypes.CreateCustomerGroupDTO[],
@MedusaContext() sharedContext: Context = {}
) {
- const data = Array.isArray(dataOrArrayOfData)
- ? dataOrArrayOfData
- : [dataOrArrayOfData]
+ const groups = await this.customerGroupService_.create(
+ dataOrArrayOfData,
+ sharedContext
+ )
- const groups = await this.customerGroupService_.create(data, sharedContext)
- const serialized = await this.baseRepository_.serialize<
- CustomerTypes.CustomerGroupDTO[]
+ return await this.baseRepository_.serialize<
+ CustomerTypes.CustomerGroupDTO | CustomerTypes.CustomerGroupDTO[]
>(groups, {
populate: true,
})
-
- return Array.isArray(dataOrArrayOfData) ? serialized : serialized[0]
}
- @InjectManager("baseRepository_")
- async retrieveCustomerGroup(
- groupId: string,
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const group = await this.customerGroupService_.retrieve(
- groupId,
- config,
- sharedContext
- )
- return await this.baseRepository_.serialize(
- group,
- { populate: true }
- )
- }
-
- async updateCustomerGroup(
+ async updateCustomerGroups(
groupId: string,
data: CustomerTypes.CustomerGroupUpdatableFields,
sharedContext?: Context
): Promise
- async updateCustomerGroup(
+ async updateCustomerGroups(
groupIds: string[],
data: CustomerTypes.CustomerGroupUpdatableFields,
sharedContext?: Context
): Promise
- async updateCustomerGroup(
+ async updateCustomerGroups(
selector: CustomerTypes.FilterableCustomerGroupProps,
data: CustomerTypes.CustomerGroupUpdatableFields,
sharedContext?: Context
): Promise
@InjectTransactionManager("baseRepository_")
- async updateCustomerGroup(
+ async updateCustomerGroups(
groupIdOrSelector:
| string
| string[]
@@ -334,29 +263,27 @@ export default class CustomerModuleService implements ICustomerModuleService {
data: CustomerTypes.CustomerGroupUpdatableFields,
@MedusaContext() sharedContext: Context = {}
) {
- let updateData: CustomerTypes.UpdateCustomerGroupDTO[] = []
- if (isString(groupIdOrSelector)) {
- updateData = [
- {
- id: groupIdOrSelector,
- ...data,
- },
- ]
- } else if (Array.isArray(groupIdOrSelector)) {
- updateData = groupIdOrSelector.map((id) => ({
+ let updateData:
+ | CustomerTypes.UpdateCustomerGroupDTO
+ | CustomerTypes.UpdateCustomerGroupDTO[]
+ | {
+ selector: CustomerTypes.FilterableCustomerGroupProps
+ data: CustomerTypes.CustomerGroupUpdatableFields
+ } = []
+
+ if (isString(groupIdOrSelector) || Array.isArray(groupIdOrSelector)) {
+ const groupIdOrSelectorArray = Array.isArray(groupIdOrSelector)
+ ? groupIdOrSelector
+ : [groupIdOrSelector]
+ updateData = groupIdOrSelectorArray.map((id) => ({
id,
...data,
}))
} else {
- const ids = await this.customerGroupService_.list(
- groupIdOrSelector,
- { select: ["id"] },
- sharedContext
- )
- updateData = ids.map(({ id }) => ({
- id,
- ...data,
- }))
+ updateData = {
+ selector: groupIdOrSelector,
+ data: data,
+ }
}
const groups = await this.customerGroupService_.update(
@@ -376,39 +303,6 @@ export default class CustomerModuleService implements ICustomerModuleService {
>(groups, { populate: true })
}
- deleteCustomerGroup(groupId: string, sharedContext?: Context): Promise
- deleteCustomerGroup(
- groupIds: string[],
- sharedContext?: Context
- ): Promise
- deleteCustomerGroup(
- selector: CustomerTypes.FilterableCustomerGroupProps,
- sharedContext?: Context
- ): Promise
-
- @InjectTransactionManager("baseRepository_")
- async deleteCustomerGroup(
- groupIdOrSelector:
- | string
- | string[]
- | CustomerTypes.FilterableCustomerGroupProps,
- @MedusaContext() sharedContext: Context = {}
- ) {
- let toDelete = Array.isArray(groupIdOrSelector)
- ? groupIdOrSelector
- : [groupIdOrSelector as string]
- if (isObject(groupIdOrSelector)) {
- const ids = await this.customerGroupService_.list(
- groupIdOrSelector,
- { select: ["id"] },
- sharedContext
- )
- toDelete = ids.map(({ id }) => id)
- }
-
- return await this.customerGroupService_.delete(toDelete, sharedContext)
- }
-
async addCustomerToGroup(
groupCustomerPair: CustomerTypes.GroupCustomerPair,
sharedContext?: Context
@@ -425,17 +319,20 @@ export default class CustomerModuleService implements ICustomerModuleService {
@MedusaContext() sharedContext: Context = {}
): Promise<{ id: string } | { id: string }[]> {
const groupCustomers = await this.customerGroupCustomerService_.create(
- Array.isArray(data) ? data : [data],
+ data,
sharedContext
)
if (Array.isArray(data)) {
- return groupCustomers.map((gc) => ({ id: gc.id }))
+ return (groupCustomers as unknown as TCustomerGroupCustomer[]).map(
+ (gc) => ({ id: gc.id })
+ )
}
- return { id: groupCustomers[0].id }
+ return { id: groupCustomers.id }
}
+ // TODO: should be createAddresses to conform to the convention
async addAddresses(
addresses: CustomerTypes.CreateCustomerAddressDTO[],
sharedContext?: Context
@@ -445,7 +342,7 @@ export default class CustomerModuleService implements ICustomerModuleService {
sharedContext?: Context
): Promise
- @InjectTransactionManager("baseRepository_")
+ @InjectManager("baseRepository_")
async addAddresses(
data:
| CustomerTypes.CreateCustomerAddressDTO
@@ -454,13 +351,10 @@ export default class CustomerModuleService implements ICustomerModuleService {
): Promise<
CustomerTypes.CustomerAddressDTO | CustomerTypes.CustomerAddressDTO[]
> {
- const addresses = await this.addressService_.create(
- Array.isArray(data) ? data : [data],
- sharedContext
+ const addresses = await this.addAddresses_(data, sharedContext).catch(
+ this.handleDbErrors
)
- await this.flush(sharedContext).catch(this.handleDbErrors)
-
const serialized = await this.baseRepository_.serialize<
CustomerTypes.CustomerAddressDTO[]
>(addresses, { populate: true })
@@ -472,24 +366,39 @@ export default class CustomerModuleService implements ICustomerModuleService {
return serialized[0]
}
- async updateAddress(
+ @InjectTransactionManager("baseRepository_")
+ private async addAddresses_(
+ data:
+ | CustomerTypes.CreateCustomerAddressDTO
+ | CustomerTypes.CreateCustomerAddressDTO[],
+ @MedusaContext() sharedContext: Context = {}
+ ) {
+ const addresses = await this.addressService_.create(
+ Array.isArray(data) ? data : [data],
+ sharedContext
+ )
+
+ return addresses
+ }
+
+ async updateAddresses(
addressId: string,
data: CustomerTypes.UpdateCustomerAddressDTO,
sharedContext?: Context
): Promise
- async updateAddress(
+ async updateAddresses(
addressIds: string[],
data: CustomerTypes.UpdateCustomerAddressDTO,
sharedContext?: Context
): Promise
- async updateAddress(
+ async updateAddresses(
selector: CustomerTypes.FilterableCustomerAddressProps,
data: CustomerTypes.UpdateCustomerAddressDTO,
sharedContext?: Context
): Promise
@InjectTransactionManager("baseRepository_")
- async updateAddress(
+ async updateAddresses(
addressIdOrSelector:
| string
| string[]
@@ -497,7 +406,12 @@ export default class CustomerModuleService implements ICustomerModuleService {
data: CustomerTypes.UpdateCustomerAddressDTO,
@MedusaContext() sharedContext: Context = {}
) {
- let updateData: CustomerTypes.UpdateCustomerAddressDTO[] = []
+ let updateData:
+ | CustomerTypes.UpdateCustomerAddressDTO[]
+ | {
+ selector: CustomerTypes.FilterableCustomerAddressProps
+ data: CustomerTypes.UpdateCustomerAddressDTO
+ } = []
if (isString(addressIdOrSelector)) {
updateData = [
{
@@ -511,15 +425,10 @@ export default class CustomerModuleService implements ICustomerModuleService {
...data,
}))
} else {
- const ids = await this.addressService_.list(
- addressIdOrSelector,
- { select: ["id"] },
- sharedContext
- )
- updateData = ids.map(({ id }) => ({
- id,
- ...data,
- }))
+ updateData = {
+ selector: addressIdOrSelector,
+ data,
+ }
}
const addresses = await this.addressService_.update(
@@ -540,78 +449,6 @@ export default class CustomerModuleService implements ICustomerModuleService {
return serialized
}
- async deleteAddress(addressId: string, sharedContext?: Context): Promise
- async deleteAddress(
- addressIds: string[],
- sharedContext?: Context
- ): Promise
- async deleteAddress(
- selector: CustomerTypes.FilterableCustomerAddressProps,
- sharedContext?: Context
- ): Promise
-
- @InjectTransactionManager("baseRepository_")
- async deleteAddress(
- addressIdOrSelector:
- | string
- | string[]
- | CustomerTypes.FilterableCustomerAddressProps,
- @MedusaContext() sharedContext: Context = {}
- ) {
- let toDelete = Array.isArray(addressIdOrSelector)
- ? addressIdOrSelector
- : [addressIdOrSelector as string]
-
- if (isObject(addressIdOrSelector)) {
- const ids = await this.addressService_.list(
- addressIdOrSelector,
- { select: ["id"] },
- sharedContext
- )
- toDelete = ids.map(({ id }) => id)
- }
-
- await this.addressService_.delete(toDelete, sharedContext)
- }
-
- @InjectManager("baseRepository_")
- async listAddresses(
- filters?: CustomerTypes.FilterableCustomerAddressProps,
- config?: FindConfig,
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const addresses = await this.addressService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize<
- CustomerTypes.CustomerAddressDTO[]
- >(addresses, { populate: true })
- }
-
- @InjectManager("baseRepository_")
- async listAndCountAddresses(
- filters?: CustomerTypes.FilterableCustomerAddressProps,
- config?: FindConfig,
- @MedusaContext() sharedContext: Context = {}
- ): Promise<[CustomerTypes.CustomerAddressDTO[], number]> {
- const [addresses, count] = await this.addressService_.listAndCount(
- filters,
- config,
- sharedContext
- )
-
- return [
- await this.baseRepository_.serialize(
- addresses,
- { populate: true }
- ),
- count,
- ]
- }
-
async removeCustomerFromGroup(
groupCustomerPair: CustomerTypes.GroupCustomerPair,
sharedContext?: Context
@@ -636,153 +473,6 @@ export default class CustomerModuleService implements ICustomerModuleService {
)
}
- @InjectManager("baseRepository_")
- async listCustomerGroupRelations(
- filters?: CustomerTypes.FilterableCustomerGroupCustomerProps,
- config?: FindConfig,
- @MedusaContext() sharedContext: Context = {}
- ) {
- const groupCustomers = await this.customerGroupCustomerService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize<
- CustomerTypes.CustomerGroupCustomerDTO[]
- >(groupCustomers, {
- populate: true,
- })
- }
-
- @InjectManager("baseRepository_")
- async listCustomerGroups(
- filters: CustomerTypes.FilterableCustomerGroupProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const groups = await this.customerGroupService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize<
- CustomerTypes.CustomerGroupDTO[]
- >(groups, {
- populate: true,
- })
- }
-
- @InjectManager("baseRepository_")
- async listAndCountCustomerGroups(
- filters: CustomerTypes.FilterableCustomerGroupProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise<[CustomerTypes.CustomerGroupDTO[], number]> {
- const [groups, count] = await this.customerGroupService_.listAndCount(
- filters,
- config,
- sharedContext
- )
-
- return [
- await this.baseRepository_.serialize(
- groups,
- {
- populate: true,
- }
- ),
- count,
- ]
- }
-
- @InjectTransactionManager("baseRepository_")
- async softDeleteCustomerGroup<
- TReturnableLinkableKeys extends string = string
- >(
- groupIds: string[],
- config: SoftDeleteReturn = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const [_, cascadedEntitiesMap] =
- await this.customerGroupService_.softDelete(groupIds, sharedContext)
- return config.returnLinkableKeys
- ? mapObjectTo>(
- cascadedEntitiesMap,
- entityNameToLinkableKeysMap,
- {
- pick: config.returnLinkableKeys,
- }
- )
- : void 0
- }
-
- @InjectTransactionManager("baseRepository_")
- async restoreCustomerGroup(
- groupIds: string[],
- config: RestoreReturn = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const [_, cascadedEntitiesMap] = await this.customerGroupService_.restore(
- groupIds,
- sharedContext
- )
- return config.returnLinkableKeys
- ? mapObjectTo>(
- cascadedEntitiesMap,
- entityNameToLinkableKeysMap,
- {
- pick: config.returnLinkableKeys,
- }
- )
- : void 0
- }
-
- @InjectTransactionManager("baseRepository_")
- async softDelete(
- customerIds: string[],
- config: SoftDeleteReturn = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const [_, cascadedEntitiesMap] = await this.customerService_.softDelete(
- customerIds,
- sharedContext
- )
-
- return config.returnLinkableKeys
- ? mapObjectTo>(
- cascadedEntitiesMap,
- entityNameToLinkableKeysMap,
- {
- pick: config.returnLinkableKeys,
- }
- )
- : void 0
- }
-
- @InjectTransactionManager("baseRepository_")
- async restore(
- customerIds: string[],
- config: RestoreReturn = {},
- @MedusaContext() sharedContext: Context = {}
- ) {
- const [_, cascadedEntitiesMap] = await this.customerService_.restore(
- customerIds,
- sharedContext
- )
-
- return config.returnLinkableKeys
- ? mapObjectTo>(
- cascadedEntitiesMap,
- entityNameToLinkableKeysMap,
- {
- pick: config.returnLinkableKeys,
- }
- )
- : void 0
- }
-
private async flush(context: Context) {
const em = (context.manager ?? context.transactionManager) as EntityManager
await em.flush()
diff --git a/packages/customer/src/services/customer.ts b/packages/customer/src/services/customer.ts
deleted file mode 100644
index 3aec4769e441d..0000000000000
--- a/packages/customer/src/services/customer.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { CustomerTypes, DAL } from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-import { Customer } from "@models"
-
-type InjectedDependencies = {
- customerRepository: DAL.RepositoryService
-}
-
-export default class CustomerService<
- TEntity extends Customer = Customer
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CustomerTypes.CreateCustomerDTO
- update: CustomerTypes.UpdateCustomerDTO
- }
->(Customer) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/customer/src/services/index.ts b/packages/customer/src/services/index.ts
index 07e39a5c1c62d..398679936abf0 100644
--- a/packages/customer/src/services/index.ts
+++ b/packages/customer/src/services/index.ts
@@ -1,5 +1 @@
-export { default as AddressService } from "./address"
-export { default as CustomerGroupService } from "./customer-group"
-export { default as CustomerService } from "./customer"
export { default as CustomerModuleService } from "./customer-module"
-export { default as CustomerGroupCustomerService } from "./customer-group-customer"
diff --git a/packages/customer/src/types/index.ts b/packages/customer/src/types/index.ts
index e70f89b103e9e..c993481e0d955 100644
--- a/packages/customer/src/types/index.ts
+++ b/packages/customer/src/types/index.ts
@@ -1,5 +1,8 @@
import { Logger } from "@medusajs/types"
-export * from "./address"
+
+export * as ServiceTypes from "./services"
+export * from "./services"
+
export type InitializeModuleInjectableDependencies = {
logger?: Logger
}
diff --git a/packages/customer/src/types/address.ts b/packages/customer/src/types/services/address.ts
similarity index 100%
rename from packages/customer/src/types/address.ts
rename to packages/customer/src/types/services/address.ts
diff --git a/packages/customer/src/types/services/customer-group-customer.ts b/packages/customer/src/types/services/customer-group-customer.ts
new file mode 100644
index 0000000000000..f51d3b57abbee
--- /dev/null
+++ b/packages/customer/src/types/services/customer-group-customer.ts
@@ -0,0 +1,5 @@
+export interface CreateCustomerGroupCustomerDTO {
+ customer_id: string
+ customer_group_id: string
+ created_by?: string
+}
diff --git a/packages/customer/src/types/services/index.ts b/packages/customer/src/types/services/index.ts
new file mode 100644
index 0000000000000..c7ac451a5e8be
--- /dev/null
+++ b/packages/customer/src/types/services/index.ts
@@ -0,0 +1,2 @@
+export * from "./address"
+export * from "./customer-group-customer"
diff --git a/packages/design-system/ui-preset/package.json b/packages/design-system/ui-preset/package.json
index 53bb8ebf8f041..22776839f6483 100644
--- a/packages/design-system/ui-preset/package.json
+++ b/packages/design-system/ui-preset/package.json
@@ -31,7 +31,7 @@
},
"devDependencies": {
"@medusajs/toolbox": "^0.0.1",
- "tailwindcss": "^3.3.2",
+ "tailwindcss": "^3.4.1",
"tsup": "^7.1.0",
"typescript": "^5.1.6"
},
diff --git a/packages/design-system/ui/package.json b/packages/design-system/ui/package.json
index d0b0734d22ba1..9653eff581901 100644
--- a/packages/design-system/ui/package.json
+++ b/packages/design-system/ui/package.json
@@ -72,7 +72,7 @@
"resize-observer-polyfill": "^1.5.1",
"rimraf": "^5.0.1",
"storybook": "^7.0.23",
- "tailwindcss": "^3.3.2",
+ "tailwindcss": "^3.4.1",
"tsc-alias": "^1.8.7",
"typescript": "^5.1.6",
"vite": "^4.3.9",
diff --git a/packages/design-system/ui/src/components/table/table.tsx b/packages/design-system/ui/src/components/table/table.tsx
index 246371cbadf77..40f58e18d9028 100644
--- a/packages/design-system/ui/src/components/table/table.tsx
+++ b/packages/design-system/ui/src/components/table/table.tsx
@@ -49,7 +49,7 @@ const Cell = React.forwardRef<
HTMLTableCellElement,
React.HTMLAttributes
>(({ className, ...props }, ref) => (
- |
+ |
))
Cell.displayName = "Table.Cell"
@@ -72,7 +72,11 @@ const HeaderCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes
>(({ className, ...props }, ref) => (
- |
+ |
))
HeaderCell.displayName = "Table.HeaderCell"
diff --git a/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/callback/route.ts b/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/callback/route.ts
new file mode 100644
index 0000000000000..54066dce4f3fd
--- /dev/null
+++ b/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/callback/route.ts
@@ -0,0 +1,46 @@
+import { AuthenticationInput, IAuthModuleService } from "@medusajs/types"
+import { MedusaRequest, MedusaResponse } from "../../../../../types/routing"
+
+import { MedusaError } from "@medusajs/utils"
+import { ModuleRegistrationName } from "@medusajs/modules-sdk"
+
+export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
+ const { scope, authProvider } = req.params
+
+ const service: IAuthModuleService = req.scope.resolve(
+ ModuleRegistrationName.AUTH
+ )
+
+ const authData = {
+ url: req.url,
+ headers: req.headers,
+ query: req.query,
+ body: req.body,
+ authScope: scope,
+ protocol: req.protocol,
+ } as AuthenticationInput
+
+ const authResult = await service.validateCallback(authProvider, authData)
+
+ const { success, error, authUser, location } = authResult
+ if (location) {
+ res.redirect(location)
+ return
+ }
+
+ if (success) {
+ req.session.auth_user = authUser
+ req.session.scope = authUser.scope
+
+ return res.status(200).json({ authUser })
+ }
+
+ throw new MedusaError(
+ MedusaError.Types.UNAUTHORIZED,
+ error || "Authentication failed"
+ )
+}
+
+export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
+ await GET(req, res)
+}
diff --git a/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/route.ts b/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/route.ts
new file mode 100644
index 0000000000000..7d3873a320ccd
--- /dev/null
+++ b/packages/medusa/src/api-v2/auth/[scope]/[authProvider]/route.ts
@@ -0,0 +1,46 @@
+import { AuthenticationInput, IAuthModuleService } from "@medusajs/types"
+import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
+
+import { MedusaError } from "@medusajs/utils"
+import { ModuleRegistrationName } from "@medusajs/modules-sdk"
+
+export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
+ const { scope, authProvider } = req.params
+
+ const service: IAuthModuleService = req.scope.resolve(
+ ModuleRegistrationName.AUTH
+ )
+
+ const authData = {
+ url: req.url,
+ headers: req.headers,
+ query: req.query,
+ body: req.body,
+ authScope: scope,
+ protocol: req.protocol,
+ } as AuthenticationInput
+
+ const authResult = await service.authenticate(authProvider, authData)
+
+ const { success, error, authUser, location } = authResult
+ if (location) {
+ res.redirect(location)
+ return
+ }
+
+ if (success) {
+ req.session.auth_user = authUser
+ req.session.scope = authUser.scope
+
+ return res.status(200).json({ authUser })
+ }
+
+ throw new MedusaError(
+ MedusaError.Types.UNAUTHORIZED,
+ error || "Authentication failed"
+ )
+}
+
+export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
+ await GET(req, res)
+}
diff --git a/packages/medusa/src/api-v2/store/customers/me/route.ts b/packages/medusa/src/api-v2/store/customers/me/route.ts
index 22a9746d97428..83b654f84cbb5 100644
--- a/packages/medusa/src/api-v2/store/customers/me/route.ts
+++ b/packages/medusa/src/api-v2/store/customers/me/route.ts
@@ -1,8 +1,9 @@
-import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
+import { ModuleRegistrationName } from "@medusajs/modules-sdk"
+
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
- const id = req.auth_user!.app_metadata.customer_id
+ const id = req.auth_user!.app_metadata?.customer_id
const customerModule = req.scope.resolve(ModuleRegistrationName.CUSTOMER)
diff --git a/packages/medusa/src/api-v2/store/customers/middlewares.ts b/packages/medusa/src/api-v2/store/customers/middlewares.ts
index c60b5f1ea2598..f0bf0e8c2821a 100644
--- a/packages/medusa/src/api-v2/store/customers/middlewares.ts
+++ b/packages/medusa/src/api-v2/store/customers/middlewares.ts
@@ -7,9 +7,10 @@ import {
StorePostCustomersMeAddressesAddressReq,
StoreGetCustomersMeAddressesParams,
} from "./validators"
-import authenticate from "../../../utils/authenticate-middleware"
import * as QueryConfig from "./query-config"
+import { authenticate } from "../../../utils/authenticate-middleware"
+
export const storeCustomerRoutesMiddlewares: MiddlewareRoute[] = [
{
method: "ALL",
diff --git a/packages/medusa/src/api-v2/store/customers/query-config.ts b/packages/medusa/src/api-v2/store/customers/query-config.ts
index 5a54fd3bcea0e..7a503843c647f 100644
--- a/packages/medusa/src/api-v2/store/customers/query-config.ts
+++ b/packages/medusa/src/api-v2/store/customers/query-config.ts
@@ -17,7 +17,7 @@ export const defaultStoreCustomersFields: (keyof CustomerDTO)[] = [
]
export const retrieveTransformQueryConfig = {
- defaultFields: defaultStoreCustomersFields,
+ defaultFields: defaultStoreCustomersFields as string[],
defaultRelations: defaultStoreCustomersRelations,
allowedRelations: allowedStoreCustomersRelations,
isList: false,
diff --git a/packages/medusa/src/api-v2/store/customers/route.ts b/packages/medusa/src/api-v2/store/customers/route.ts
index b7600fc55dd78..14fb4f1653e91 100644
--- a/packages/medusa/src/api-v2/store/customers/route.ts
+++ b/packages/medusa/src/api-v2/store/customers/route.ts
@@ -1,8 +1,30 @@
import { MedusaRequest, MedusaResponse } from "../../../types/routing"
-import { createCustomerAccountWorkflow } from "@medusajs/core-flows"
+
+import {
+ ContainerRegistrationKeys,
+ remoteQueryObjectFromString,
+} from "@medusajs/utils"
import { CreateCustomerDTO } from "@medusajs/types"
+import { createCustomerAccountWorkflow } from "@medusajs/core-flows"
export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
+ if (req.auth_user?.app_metadata?.customer_id) {
+ const remoteQuery = req.scope.resolve(
+ ContainerRegistrationKeys.REMOTE_QUERY
+ )
+
+ const query = remoteQueryObjectFromString({
+ entryPoint: "customer",
+ variables: { id: req.auth_user.app_metadata.customer_id },
+ fields: [],
+ })
+ const [customer] = await remoteQuery(query)
+
+ res.status(200).json({ customer })
+
+ return
+ }
+
const createCustomers = createCustomerAccountWorkflow(req.scope)
const customersData = req.validatedBody as CreateCustomerDTO
@@ -10,5 +32,9 @@ export const POST = async (req: MedusaRequest, res: MedusaResponse) => {
input: { customersData, authUserId: req.auth_user!.id },
})
+ // Set customer_id on session user if we are in session
+ if (req.session.auth_user) {
+ req.session.auth_user.app_metadata.customer_id = result.id
+ }
res.status(200).json({ customer: result })
}
diff --git a/packages/medusa/src/types/routing.ts b/packages/medusa/src/types/routing.ts
index 8a17b7eee061c..d270d7adc87cc 100644
--- a/packages/medusa/src/types/routing.ts
+++ b/packages/medusa/src/types/routing.ts
@@ -1,11 +1,13 @@
+import type { Customer, User } from "../models"
import type { NextFunction, Request, Response } from "express"
-import type { Customer, User } from "../models"
+import { AuthUserDTO } from "@medusajs/types"
import type { MedusaContainer } from "./global"
export interface MedusaRequest extends Request {
user?: (User | Customer) & { customer_id?: string; userId?: string }
scope: MedusaContainer
+ session?: any
requestId?: string
auth_user?: { id: string; app_metadata: Record; scope: string }
}
diff --git a/packages/medusa/src/utils/authenticate-middleware.ts b/packages/medusa/src/utils/authenticate-middleware.ts
index 0417017ef4ce3..ffc2326a09f53 100644
--- a/packages/medusa/src/utils/authenticate-middleware.ts
+++ b/packages/medusa/src/utils/authenticate-middleware.ts
@@ -1,22 +1,20 @@
-import { ModuleRegistrationName } from "@medusajs/modules-sdk"
import { AuthUserDTO, IAuthModuleService } from "@medusajs/types"
-import { NextFunction, RequestHandler } from "express"
import { MedusaRequest, MedusaResponse } from "../types/routing"
+import { NextFunction, RequestHandler } from "express"
+
+import { ModuleRegistrationName } from "@medusajs/modules-sdk"
const SESSION_AUTH = "session"
const BEARER_AUTH = "bearer"
type MedusaSession = {
- auth: {
- [authScope: string]: {
- user_id: string
- }
- }
+ auth_user: AuthUserDTO
+ scope: string
}
type AuthType = "session" | "bearer"
-export default (
+export const authenticate = (
authScope: string,
authType: AuthType | AuthType[],
options: { allowUnauthenticated?: boolean } = {}
@@ -36,19 +34,18 @@ export default (
let authUser: AuthUserDTO | null = null
if (authTypes.includes(SESSION_AUTH)) {
- if (session.auth && session.auth[authScope]) {
- authUser = await authModule
- .retrieveAuthUser(session.auth[authScope].user_id)
- .catch(() => null)
+ if (session.auth_user && session.scope === authScope) {
+ authUser = session.auth_user
}
}
- if (authTypes.includes(BEARER_AUTH)) {
+ if (!authUser && authTypes.includes(BEARER_AUTH)) {
const authHeader = req.headers.authorization
if (authHeader) {
const re = /(\S+)\s+(\S+)/
const matches = authHeader.match(re)
+ // TODO: figure out how to obtain token (and store correct data in token)
if (matches) {
const tokenType = matches[1]
const token = matches[2]
diff --git a/packages/payment/integration-tests/__tests__/services/payment-module/index.spec.ts b/packages/payment/integration-tests/__tests__/services/payment-module/index.spec.ts
index 4aa4ba692695a..4f13d0822f622 100644
--- a/packages/payment/integration-tests/__tests__/services/payment-module/index.spec.ts
+++ b/packages/payment/integration-tests/__tests__/services/payment-module/index.spec.ts
@@ -116,7 +116,7 @@ describe("Payment Module Service", () => {
expect(collection.length).toEqual(1)
- await service.deletePaymentCollection(["pay-col-id-1"])
+ await service.deletePaymentCollections(["pay-col-id-1"])
collection = await service.listPaymentCollections({
id: ["pay-col-id-1"],
diff --git a/packages/payment/src/services/index.ts b/packages/payment/src/services/index.ts
index 01f593ba08ead..a4f5ea37aea2e 100644
--- a/packages/payment/src/services/index.ts
+++ b/packages/payment/src/services/index.ts
@@ -1,2 +1 @@
export { default as PaymentModuleService } from "./payment-module"
-export { default as PaymentCollectionService } from "./payment-collection"
diff --git a/packages/payment/src/services/payment-collection.ts b/packages/payment/src/services/payment-collection.ts
deleted file mode 100644
index abeef3e6625e7..0000000000000
--- a/packages/payment/src/services/payment-collection.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { PaymentCollection } from "@models"
-import {
- CreatePaymentCollectionDTO,
- DAL,
- UpdatePaymentCollectionDTO,
-} from "@medusajs/types"
-import { ModulesSdkUtils } from "@medusajs/utils"
-
-type InjectedDependencies = {
- paymentCollectionRepository: DAL.RepositoryService
-}
-
-export default class PaymentCollectionService<
- TEntity extends PaymentCollection = PaymentCollection
-> extends ModulesSdkUtils.abstractServiceFactory<
- InjectedDependencies,
- {
- create: CreatePaymentCollectionDTO
- update: UpdatePaymentCollectionDTO
- }
->(PaymentCollection) {
- constructor(container: InjectedDependencies) {
- // @ts-ignore
- super(...arguments)
- }
-}
diff --git a/packages/payment/src/services/payment-module.ts b/packages/payment/src/services/payment-module.ts
index 93d4a1310e4e1..1e62e664311eb 100644
--- a/packages/payment/src/services/payment-module.ts
+++ b/packages/payment/src/services/payment-module.ts
@@ -4,11 +4,10 @@ import {
CreatePaymentDTO,
CreatePaymentSessionDTO,
DAL,
- FilterablePaymentCollectionProps,
- FindConfig,
InternalModuleDeclaration,
IPaymentModuleService,
ModuleJoinerConfig,
+ ModulesSdkTypes,
PaymentCollectionDTO,
PaymentDTO,
SetPaymentSessionsDTO,
@@ -16,28 +15,64 @@ import {
UpdatePaymentDTO,
} from "@medusajs/types"
import {
- InjectManager,
InjectTransactionManager,
MedusaContext,
+ ModulesSdkUtils,
} from "@medusajs/utils"
-import * as services from "@services"
-
-import { joinerConfig } from "../joiner-config"
+import { entityNameToLinkableKeysMap, joinerConfig } from "../joiner-config"
+import {
+ Capture,
+ Payment,
+ PaymentCollection,
+ PaymentMethodToken,
+ PaymentProvider,
+ PaymentSession,
+ Refund,
+} from "@models"
type InjectedDependencies = {
baseRepository: DAL.RepositoryService
- paymentCollectionService: services.PaymentCollectionService
+ paymentCollectionService: ModulesSdkTypes.InternalModuleService
}
-export default class PaymentModuleService implements IPaymentModuleService {
+const generateMethodForModels = [
+ Capture,
+ PaymentCollection,
+ PaymentMethodToken,
+ PaymentProvider,
+ PaymentSession,
+ Refund,
+]
+
+export default class PaymentModuleService<
+ TPaymentCollection extends PaymentCollection = PaymentCollection
+ >
+ extends ModulesSdkUtils.abstractModuleServiceFactory<
+ // TODO revisit when moving forward frane
+ InjectedDependencies,
+ PaymentDTO,
+ {
+ Capture: { dto: any }
+ PaymentCollection: { dto: any }
+ PaymentMethodToken: { dto: any }
+ PaymentProvider: { dto: any }
+ PaymentSession: { dto: any }
+ Refund: { dto: any }
+ }
+ >(Payment, generateMethodForModels, entityNameToLinkableKeysMap)
+ implements IPaymentModuleService
+{
protected baseRepository_: DAL.RepositoryService
- protected paymentCollectionService_: services.PaymentCollectionService
+ protected paymentCollectionService_: ModulesSdkTypes.InternalModuleService
constructor(
{ baseRepository, paymentCollectionService }: InjectedDependencies,
protected readonly moduleDeclaration: InternalModuleDeclaration
) {
+ // @ts-ignore
+ super(...arguments)
+
this.baseRepository_ = baseRepository
this.paymentCollectionService_ = paymentCollectionService
@@ -105,85 +140,6 @@ export default class PaymentModuleService implements IPaymentModuleService {
)
}
- deletePaymentCollection(
- paymentCollectionId: string[],
- sharedContext?: Context
- ): Promise
- deletePaymentCollection(
- paymentCollectionId: string,
- sharedContext?: Context
- ): Promise
-
- @InjectTransactionManager("baseRepository_")
- async deletePaymentCollection(
- ids: string | string[],
- @MedusaContext() sharedContext?: Context
- ): Promise {
- const paymentCollectionIds = Array.isArray(ids) ? ids : [ids]
- await this.paymentCollectionService_.delete(
- paymentCollectionIds,
- sharedContext
- )
- }
-
- @InjectManager("baseRepository_")
- async retrievePaymentCollection(
- paymentCollectionId: string,
- config: FindConfig = {},
- @MedusaContext() sharedContext: Context = {}
- ): Promise {
- const paymentCollection = await this.paymentCollectionService_.retrieve(
- paymentCollectionId,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize(
- paymentCollection,
- { populate: true }
- )
- }
-
- @InjectManager("baseRepository_")
- async listPaymentCollections(
- filters: FilterablePaymentCollectionProps = {},
- config: FindConfig = {},
- @MedusaContext() sharedContext?: Context
- ): Promise {
- const paymentCollections = await this.paymentCollectionService_.list(
- filters,
- config,
- sharedContext
- )
-
- return await this.baseRepository_.serialize