feat: Add notification endpoints for admin (#8196)

This commit is contained in:
Stevche Radevski
2024-07-19 22:00:53 +02:00
committed by GitHub
parent ecc97076b5
commit 56f2ddc4b6
15 changed files with 209 additions and 3 deletions

View File

@@ -5,6 +5,7 @@ import { FulfillmentProvider } from "./fulfillment-provider"
import { FulfillmentSet } from "./fulfillment-set"
import { InventoryItem } from "./inventory-item"
import { Invite } from "./invite"
import { Notification } from "./notification"
import { Order } from "./order"
import { PriceList } from "./price-list"
import { PricePreference } from "./price-preference"
@@ -44,6 +45,7 @@ export class Admin {
public shippingOption: ShippingOption
public shippingProfile: ShippingProfile
public inventoryItem: InventoryItem
public notification: Notification
public order: Order
public taxRate: TaxRate
public taxRegion: TaxRegion
@@ -71,6 +73,7 @@ export class Admin {
this.shippingOption = new ShippingOption(client)
this.shippingProfile = new ShippingProfile(client)
this.inventoryItem = new InventoryItem(client)
this.notification = new Notification(client)
this.order = new Order(client)
this.taxRate = new TaxRate(client)
this.taxRegion = new TaxRegion(client)

View File

@@ -0,0 +1,39 @@
import { HttpTypes } from "@medusajs/types"
import { Client } from "../client"
import { ClientHeaders } from "../types"
export class Notification {
private client: Client
constructor(client: Client) {
this.client = client
}
async retrieve(
id: string,
query?: HttpTypes.AdminNotificationParams,
headers?: ClientHeaders
) {
return await this.client.fetch<HttpTypes.AdminNotificationResponse>(
`/admin/notifications/${id}`,
{
method: "GET",
headers,
query,
}
)
}
async list(
query?: HttpTypes.AdminNotificationListParams,
headers?: ClientHeaders
) {
return await this.client.fetch<HttpTypes.AdminNotificationListResponse>(
`/admin/notifications`,
{
method: "GET",
headers,
query,
}
)
}
}

View File

@@ -12,6 +12,7 @@ export * from "./fulfillment-set"
export * from "./inventory"
export * from "./inventory-level"
export * from "./invite"
export * from "./notification"
export * from "./order"
export * from "./payment"
export * from "./price-list"
@@ -32,4 +33,3 @@ export * from "./store"
export * from "./tax-rate"
export * from "./tax-region"
export * from "./user"

View File

@@ -0,0 +1,15 @@
export interface AdminNotification {
id: string
to: string
channel: string
template: string
data?: Record<string, unknown> | null
trigger_type?: string | null
resource_id?: string | null
resource_type?: string | null
receiver_id?: string | null
original_notification_id?: string | null
external_id?: string | null
provider_id: string
created_at: Date
}

View File

@@ -0,0 +1,3 @@
export * from "./entities"
export * from "./queries"
export * from "./responses"

View File

@@ -0,0 +1,12 @@
import { BaseFilterable } from "../../../dal"
import { FindParams, SelectParams } from "../../common"
export interface AdminNotificationListParams
extends BaseFilterable<AdminNotificationListParams>,
FindParams {
q?: string
id?: string | string[]
channel?: string | string[]
}
export interface AdminNotificationParams extends SelectParams {}

View File

@@ -0,0 +1,11 @@
import { PaginatedResponse } from "../../common"
import { AdminNotification } from "./entities"
export interface AdminNotificationResponse {
notification: AdminNotification
}
export interface AdminNotificationListResponse
extends PaginatedResponse<{
notifications: AdminNotification[]
}> {}

View File

@@ -0,0 +1 @@
export * from "./admin"

View File

@@ -0,0 +1,19 @@
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../../types/routing"
import { AdminGetNotificationParamsType } from "../validators"
import { refetchEntity } from "../../../utils/refetch-entity"
export const GET = async (
req: AuthenticatedMedusaRequest<AdminGetNotificationParamsType>,
res: MedusaResponse
) => {
const notification = await refetchEntity(
"notification",
req.params.id,
req.scope,
req.remoteQueryConfig.fields
)
res.status(200).json({ notification })
}

View File

@@ -0,0 +1,30 @@
import { MiddlewareRoute } from "../../../loaders/helpers/routing/types"
import { validateAndTransformQuery } from "../../utils/validate-query"
import * as QueryConfig from "./query-config"
import {
AdminGetNotificationParams,
AdminGetNotificationsParams,
} from "./validators"
export const adminNotificationRoutesMiddlewares: MiddlewareRoute[] = [
{
method: ["GET"],
matcher: "/admin/notifications",
middlewares: [
validateAndTransformQuery(
AdminGetNotificationsParams,
QueryConfig.listTransformQueryConfig
),
],
},
{
method: ["GET"],
matcher: "/admin/notifications/:id",
middlewares: [
validateAndTransformQuery(
AdminGetNotificationParams,
QueryConfig.retrieveTransformQueryConfig
),
],
},
]

View File

@@ -0,0 +1,23 @@
export const defaultAdminNotificationFields = [
"id",
"to",
"channel",
"template",
"data",
"trigger_type",
"resource_id",
"resource_type",
"receiver_id",
"created_at",
"updated_at",
]
export const retrieveTransformQueryConfig = {
defaults: defaultAdminNotificationFields,
isList: false,
}
export const listTransformQueryConfig = {
...retrieveTransformQueryConfig,
isList: true,
}

View File

@@ -0,0 +1,25 @@
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../types/routing"
import { AdminGetNotificationsParamsType } from "./validators"
import { refetchEntities } from "../../utils/refetch-entity"
export const GET = async (
req: AuthenticatedMedusaRequest<AdminGetNotificationsParamsType>,
res: MedusaResponse
) => {
const { rows: notifications, metadata } = await refetchEntities(
"notification",
req.filterableFields,
req.scope,
req.remoteQueryConfig.fields,
req.remoteQueryConfig.pagination
)
res.json({
notifications,
count: metadata.count,
offset: metadata.skip,
limit: metadata.take,
})
}

View File

@@ -0,0 +1,23 @@
import { z } from "zod"
import { createFindParams, createSelectParams } from "../../utils/validators"
export type AdminGetNotificationParamsType = z.infer<
typeof AdminGetNotificationParams
>
export const AdminGetNotificationParams = createSelectParams()
export type AdminGetNotificationsParamsType = z.infer<
typeof AdminGetNotificationsParams
>
export const AdminGetNotificationsParams = createFindParams({
limit: 50,
offset: 0,
}).merge(
z.object({
q: z.string().optional(),
id: z.union([z.string(), z.array(z.string())]).optional(),
channel: z.union([z.string(), z.array(z.string())]).optional(),
$and: z.lazy(() => AdminGetNotificationsParams.array()).optional(),
$or: z.lazy(() => AdminGetNotificationsParams.array()).optional(),
})
)

View File

@@ -11,6 +11,7 @@ import { adminFulfillmentSetsRoutesMiddlewares } from "./admin/fulfillment-sets/
import { adminFulfillmentsRoutesMiddlewares } from "./admin/fulfillments/middlewares"
import { adminInventoryRoutesMiddlewares } from "./admin/inventory-items/middlewares"
import { adminInviteRoutesMiddlewares } from "./admin/invites/middlewares"
import { adminNotificationRoutesMiddlewares } from "./admin/notifications/middlewares"
import { adminOrderRoutesMiddlewares } from "./admin/orders/middlewares"
import { adminPaymentRoutesMiddlewares } from "./admin/payments/middlewares"
import { adminPriceListsRoutesMiddlewares } from "./admin/price-lists/middlewares"
@@ -92,6 +93,7 @@ export const config: MiddlewaresConfig = {
...adminProductTagRoutesMiddlewares,
...adminUploadRoutesMiddlewares,
...adminFulfillmentSetsRoutesMiddlewares,
...adminNotificationRoutesMiddlewares,
...adminOrderRoutesMiddlewares,
...adminReservationRoutesMiddlewares,
...adminProductCategoryRoutesMiddlewares,

View File

@@ -5,7 +5,7 @@ import { NotificationProvider } from "./notification-provider"
export const Notification = model.define("notification", {
id: model.id({ prefix: "noti" }).primaryKey(),
// This can be an email, phone number, or username, depending on the channel.
to: model.text(),
to: model.text().searchable(),
channel: model.text(),
// The template name in the provider's system.
template: model.text(),
@@ -14,7 +14,7 @@ export const Notification = model.define("notification", {
// This can be the event name, the workflow, or anything else that can help to identify what triggered the notification.
trigger_type: model.text().nullable(),
// The ID of the resource this notification is for, if applicable. Useful for displaying relevant information in the UI
resource_id: model.text().nullable(),
resource_id: model.text().searchable().nullable(),
// The typeame of the resource this notification is for, if applicable, eg. "order"
resource_type: model.text().nullable(),
// The ID of the receiver of the notification, if applicable. This can be a customer, user, a company, or anything else.