From 336fdbcbc1ae982371eb0cf0483a175ae40d43fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Fri, 7 Mar 2025 18:56:27 -0600 Subject: [PATCH 01/28] feat(page-builder): add main Content page components - Posts Data Table - Single Column Layout - Header, ActionMenu, etc --- plugins/page-builder/package.json | 3 +- .../src/admin/components/action-menu.tsx | 100 +++++++ .../src/admin/components/header.tsx | 67 +++++ .../src/admin/layouts/single-column.tsx | 11 + .../content/components/create-post-button.tsx | 31 +++ .../content/components/posts-data-table.tsx | 257 ++++++++++++++++++ .../src/admin/routes/content/page.tsx | 41 ++- yarn.lock | 1 + 8 files changed, 498 insertions(+), 13 deletions(-) create mode 100644 plugins/page-builder/src/admin/components/action-menu.tsx create mode 100644 plugins/page-builder/src/admin/components/header.tsx create mode 100644 plugins/page-builder/src/admin/layouts/single-column.tsx create mode 100644 plugins/page-builder/src/admin/routes/content/components/create-post-button.tsx create mode 100644 plugins/page-builder/src/admin/routes/content/components/posts-data-table.tsx diff --git a/plugins/page-builder/package.json b/plugins/page-builder/package.json index 217ef87d..112b9c55 100644 --- a/plugins/page-builder/package.json +++ b/plugins/page-builder/package.json @@ -59,7 +59,8 @@ "react-dom": "^18.2.0", "ts-node": "^10.9.2", "typescript": "^5.6.2", - "vite": "^5.2.11" + "vite": "^5.2.11", + "yalc": "^1.0.0-pre.53" }, "peerDependencies": { "@medusajs/admin-sdk": "^2.6.0", diff --git a/plugins/page-builder/src/admin/components/action-menu.tsx b/plugins/page-builder/src/admin/components/action-menu.tsx new file mode 100644 index 00000000..3444f24b --- /dev/null +++ b/plugins/page-builder/src/admin/components/action-menu.tsx @@ -0,0 +1,100 @@ +import { + DropdownMenu, + IconButton, + clx, +} from "@medusajs/ui" +import { EllipsisHorizontal } from "@medusajs/icons" +import { Link } from "react-router-dom" + +export type Action = { + icon: React.ReactNode + label: string + disabled?: boolean +} & ( + | { + to: string + onClick?: never + } + | { + onClick: () => void + to?: never + } +) + +export type ActionGroup = { + actions: Action[] +} + +export type ActionMenuProps = { + groups: ActionGroup[] +} + +export const ActionMenu = ({ groups }: ActionMenuProps) => { + return ( + + + + + + + + {groups.map((group, index) => { + if (!group.actions.length) { + return null + } + + const isLast = index === groups.length - 1 + + return ( + + {group.actions.map((action, index) => { + if (action.onClick) { + return ( + { + e.stopPropagation() + action.onClick() + }} + className={clx( + "[&_svg]:text-ui-fg-subtle flex items-center gap-x-2", + { + "[&_svg]:text-ui-fg-disabled": action.disabled, + } + )} + > + {action.icon} + {action.label} + + ) + } + + return ( +
+ + e.stopPropagation()}> + {action.icon} + {action.label} + + +
+ ) + })} + {!isLast && } +
+ ) + })} +
+
+ ) +} \ No newline at end of file diff --git a/plugins/page-builder/src/admin/components/header.tsx b/plugins/page-builder/src/admin/components/header.tsx new file mode 100644 index 00000000..1d51d8be --- /dev/null +++ b/plugins/page-builder/src/admin/components/header.tsx @@ -0,0 +1,67 @@ +import { Heading, Button, Text } from "@medusajs/ui" +import React from "react" +import { Link, LinkProps } from "react-router-dom" +import { ActionMenu, ActionMenuProps } from "./action-menu" + +export type HeadingProps = { + title: string + subtitle?: string + actions?: ( + { + type: "button", + props: React.ComponentProps + link?: LinkProps + } | + { + type: "action-menu" + props: ActionMenuProps + } | + { + type: "custom" + children: React.ReactNode + } + )[] +} + +export const Header = ({ + title, + subtitle, + actions = [], +}: HeadingProps) => { + return ( +
+
+ {title} + {subtitle && ( + + {subtitle} + + )} +
+ {actions.length > 0 && ( +
+ {actions.map((action, index) => ( + <> + {action.type === "button" && ( + + )} + {action.type === "action-menu" && ( + + )} + {action.type === "custom" && action.children} + + ))} +
+ )} +
+ ) +} \ No newline at end of file diff --git a/plugins/page-builder/src/admin/layouts/single-column.tsx b/plugins/page-builder/src/admin/layouts/single-column.tsx new file mode 100644 index 00000000..73fb5f44 --- /dev/null +++ b/plugins/page-builder/src/admin/layouts/single-column.tsx @@ -0,0 +1,11 @@ +export type SingleColumnLayoutProps = { + children: React.ReactNode +} + +export const SingleColumnLayout = ({ children }: SingleColumnLayoutProps) => { + return ( +
+ {children} +
+ ) +} \ No newline at end of file diff --git a/plugins/page-builder/src/admin/routes/content/components/create-post-button.tsx b/plugins/page-builder/src/admin/routes/content/components/create-post-button.tsx new file mode 100644 index 00000000..7d163db2 --- /dev/null +++ b/plugins/page-builder/src/admin/routes/content/components/create-post-button.tsx @@ -0,0 +1,31 @@ + +import { Button, DropdownMenu } from "@medusajs/ui" +import { ChevronDown } from "@medusajs/icons" + + +const postTypes = ["post", "page"] + +type CreatePostButtonProps = { + onSelect: (type: string) => void +} + +export const CreatePostButton = ({ onSelect }: CreatePostButtonProps) => { + return ( + + + + + + + {postTypes.map((type) => ( + onSelect(type)}> +
+ {type.charAt(0).toUpperCase() + type.slice(1)} +
+
+ ))} +
+
+
+ ) +} \ No newline at end of file diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table.tsx new file mode 100644 index 00000000..56a873e7 --- /dev/null +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table.tsx @@ -0,0 +1,257 @@ +import { + createDataTableColumnHelper, + createDataTableFilterHelper, + DataTable, + DataTableFilteringState, + DataTablePaginationState, + DataTableSortingState, + useDataTable, + Badge, + Text +} from "@medusajs/ui" +import { useQuery } from "@tanstack/react-query" +import { useMemo, useState } from "react" +import { useNavigate } from "react-router-dom" + +type PostItem = { + id: string + title: string + handle: string + status: "published" | "draft" + type: string + created_at: string + updated_at: string +} + +// Mock data function - this would be replaced with actual API calls later +const fetchPostsData = async ({ + limit = 10, + offset = 0, + q = "", + status = [], + type = [], + order, +}: { + limit?: number + offset?: number + q?: string + status?: string[] + type?: string[] + order?: string +}) => { + // Mock data + const allData: PostItem[] = Array(30).fill(null).map((_, i) => { + const type = i % 2 === 0 ? "post" : "page" + return ({ + id: `${type}-${i + 1}`, + title: `${type.charAt(0).toUpperCase() + type.slice(1)} ${i + 1}`, + handle: `${type}-${i + 1}`, + status: i % 3 === 0 ? "published" : "draft", + type: type, + created_at: new Date(Date.now() - i * 86400000).toISOString(), + updated_at: new Date(Date.now() - i * 43200000).toISOString(), + })}) + + // Filter by search term + let filteredData = allData + if (q) { + filteredData = filteredData.filter( + item => item.title.toLowerCase().includes(q.toLowerCase()) || + item.handle.toLowerCase().includes(q.toLowerCase()) + ) + } + + // Filter by status + if (status.length > 0) { + filteredData = filteredData.filter(item => status.includes(item.status)) + } + + // Filter by type + if (type.length > 0) { + filteredData = filteredData.filter(item => type.includes(item.type)) + } + + // Sort data + if (order) { + const [field, direction] = order.startsWith('-') + ? [order.substring(1), 'desc'] + : [order, 'asc'] + + filteredData.sort((a, b) => { + const aValue = a[field as keyof PostItem] + const bValue = b[field as keyof PostItem] + + if (direction === 'asc') { + return aValue > bValue ? 1 : -1 + } else { + return aValue < bValue ? 1 : -1 + } + }) + } + + // Paginate + const paginatedData = filteredData.slice(offset, offset + limit) + + // Simulate network delay + await new Promise(resolve => setTimeout(resolve, 300)) + + return { + posts: paginatedData, + count: filteredData.length, + } +} + +// Create column helper +const columnHelper = createDataTableColumnHelper() + +// Define columns +const columns = [ + columnHelper.accessor("title", { + header: "Title", + enableSorting: true, + sortLabel: "Title", + }), + columnHelper.accessor("handle", { + header: "Handle", + enableSorting: true, + }), + columnHelper.accessor("status", { + header: "Status", + cell: ({ getValue }) => { + const status = getValue() + return ( + + {status === "published" ? "Published" : "Draft"} + + ) + }, + enableSorting: true, + }), + columnHelper.accessor("type", { + header: "Type", + enableSorting: true, + }), + columnHelper.accessor("created_at", { + header: "Date Created", + cell: ({ getValue }) => { + const date = new Date(getValue()) + return {date.toLocaleDateString()} + }, + enableSorting: true, + }), + columnHelper.accessor("updated_at", { + header: "Last Updated", + cell: ({ getValue }) => { + const date = new Date(getValue()) + return {date.toLocaleDateString()} + }, + enableSorting: true, + }), +] + +// Create filter helper +const filterHelper = createDataTableFilterHelper() + +// Define filters +const filters = [ + filterHelper.accessor("status", { + type: "select", + label: "Status", + options: [ + { + label: "Published", + value: "published", + }, + { + label: "Draft", + value: "draft", + }, + ], + }), + filterHelper.accessor("type", { + type: "select", + label: "Type", + options: [ + { + label: "Page", + value: "page", + }, + { + label: "Post", + value: "post", + }, + ], + }), +] + +export const PostsDataTable = () => { + const navigate = useNavigate() + const limit = 10 + const [pagination, setPagination] = useState({ + pageSize: limit, + pageIndex: 0, + }) + const [search, setSearch] = useState("") + const [filtering, setFiltering] = useState({}) + const [sorting, setSorting] = useState(null) + + const offset = useMemo(() => { + return pagination.pageIndex * limit + }, [pagination]) + + const { data, isLoading } = useQuery({ + queryFn: () => fetchPostsData({ + limit, + offset, + q: search, + status: (filtering.status || []) as string[], + type: (filtering.type || []) as string[], + order: sorting ? `${sorting.desc ? "-" : ""}${sorting.id}` : undefined, + }), + queryKey: [["posts", limit, offset, search, filtering.status, filtering.type, sorting?.id, sorting?.desc]], + }) + + const table = useDataTable({ + columns, + data: data?.posts || [], + getRowId: (row) => row.id, + rowCount: data?.count || 0, + isLoading, + pagination: { + state: pagination, + onPaginationChange: setPagination, + }, + search: { + state: search, + onSearchChange: setSearch, + }, + filtering: { + state: filtering, + onFilteringChange: setFiltering, + }, + filters, + sorting: { + state: sorting, + onSortingChange: setSorting, + }, + onRowClick: (row) => { + navigate(`editor/test`) // TODO: change to the actual content detail page + }, + }) + + return ( + + +
+ +
+ + +
+
+
+ + +
+ ) +} \ No newline at end of file diff --git a/plugins/page-builder/src/admin/routes/content/page.tsx b/plugins/page-builder/src/admin/routes/content/page.tsx index bc138983..0a3d1fda 100644 --- a/plugins/page-builder/src/admin/routes/content/page.tsx +++ b/plugins/page-builder/src/admin/routes/content/page.tsx @@ -1,20 +1,37 @@ -import { Container, Heading, Button } from "@medusajs/ui" +import { Container } from "@medusajs/ui" import { defineRouteConfig } from "@medusajs/admin-sdk" import { DocumentText } from "@medusajs/icons" -import { Link } from "react-router-dom" +import { useNavigate } from "react-router-dom" +import { SingleColumnLayout } from "../../layouts/single-column" +import { Header } from "../../components/header" +import { CreatePostButton } from "./components/create-post-button" +import { PostsDataTable } from "./components/posts-data-table" const ContentPage = () => { + const navigate = useNavigate() + + const handleCreatePost = (type: string) => { + navigate(`editor/test`) // TODO: change to the correct path + // navigate(`/editor/${type}/new`) + } + return ( - -
- Content -
-
- - - -
-
+ + +
+ } + ]} + /> +
+ +
+ + ) } diff --git a/yarn.lock b/yarn.lock index 939f696d..b08990ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1885,6 +1885,7 @@ __metadata: ts-node: "npm:^10.9.2" typescript: "npm:^5.6.2" vite: "npm:^5.2.11" + yalc: "npm:^1.0.0-pre.53" peerDependencies: "@medusajs/admin-sdk": ^2.6.0 "@medusajs/cli": ^2.6.0 From f9805960a27d12d6c587bdf2ffc5c9c0a6a952d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Tue, 11 Mar 2025 09:14:13 -0600 Subject: [PATCH 02/28] feat(page-builder): simplify content page and create data table components - Remove CreatePostButton component and replace with simple Create button - Add comprehensive PostsDataTable with filtering, sorting, and mock data - Streamline content page layout and navigation --- .../content/components/create-post-button.tsx | 31 ---- .../index.tsx} | 170 ++++++++---------- .../use-posts-data-table-columns.tsx | 121 +++++++++++++ .../src/admin/routes/content/page.tsx | 11 +- 4 files changed, 195 insertions(+), 138 deletions(-) delete mode 100644 plugins/page-builder/src/admin/routes/content/components/create-post-button.tsx rename plugins/page-builder/src/admin/routes/content/components/{posts-data-table.tsx => posts-data-table/index.tsx} (52%) create mode 100644 plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx diff --git a/plugins/page-builder/src/admin/routes/content/components/create-post-button.tsx b/plugins/page-builder/src/admin/routes/content/components/create-post-button.tsx deleted file mode 100644 index 7d163db2..00000000 --- a/plugins/page-builder/src/admin/routes/content/components/create-post-button.tsx +++ /dev/null @@ -1,31 +0,0 @@ - -import { Button, DropdownMenu } from "@medusajs/ui" -import { ChevronDown } from "@medusajs/icons" - - -const postTypes = ["post", "page"] - -type CreatePostButtonProps = { - onSelect: (type: string) => void -} - -export const CreatePostButton = ({ onSelect }: CreatePostButtonProps) => { - return ( - - - - - - - {postTypes.map((type) => ( - onSelect(type)}> -
- {type.charAt(0).toUpperCase() + type.slice(1)} -
-
- ))} -
-
-
- ) -} \ No newline at end of file diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx similarity index 52% rename from plugins/page-builder/src/admin/routes/content/components/posts-data-table.tsx rename to plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx index 56a873e7..a01bf97e 100644 --- a/plugins/page-builder/src/admin/routes/content/components/posts-data-table.tsx +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx @@ -1,33 +1,21 @@ -import { - createDataTableColumnHelper, +import { createDataTableFilterHelper, DataTable, DataTableFilteringState, DataTablePaginationState, DataTableSortingState, useDataTable, - Badge, - Text -} from "@medusajs/ui" -import { useQuery } from "@tanstack/react-query" -import { useMemo, useState } from "react" -import { useNavigate } from "react-router-dom" - -type PostItem = { - id: string - title: string - handle: string - status: "published" | "draft" - type: string - created_at: string - updated_at: string -} +} from '@medusajs/ui' +import { useQuery } from '@tanstack/react-query' +import { useMemo, useState } from 'react' + import { useNavigate } from 'react-router-dom' +import { PostItem, usePostsDataTableColumns } from './use-posts-data-table-columns' // Mock data function - this would be replaced with actual API calls later const fetchPostsData = async ({ limit = 10, offset = 0, - q = "", + q = '', status = [], type = [], order, @@ -40,47 +28,51 @@ const fetchPostsData = async ({ order?: string }) => { // Mock data - const allData: PostItem[] = Array(30).fill(null).map((_, i) => { - const type = i % 2 === 0 ? "post" : "page" - return ({ - id: `${type}-${i + 1}`, - title: `${type.charAt(0).toUpperCase() + type.slice(1)} ${i + 1}`, - handle: `${type}-${i + 1}`, - status: i % 3 === 0 ? "published" : "draft", - type: type, - created_at: new Date(Date.now() - i * 86400000).toISOString(), - updated_at: new Date(Date.now() - i * 43200000).toISOString(), - })}) + const allData: PostItem[] = Array(30) + .fill(null) + .map((_, i) => { + const type = i % 2 === 0 ? 'post' : 'page' + return { + id: `${type}-${i + 1}`, + title: `${type.charAt(0).toUpperCase() + type.slice(1)} ${i + 1}`, + handle: `${type}-${i + 1}`, + status: i % 3 === 0 ? 'published' : 'draft', + type: type, + created_at: new Date(Date.now() - i * 86400000).toISOString(), + updated_at: new Date(Date.now() - i * 43200000).toISOString(), + } + }) // Filter by search term let filteredData = allData if (q) { filteredData = filteredData.filter( - item => item.title.toLowerCase().includes(q.toLowerCase()) || - item.handle.toLowerCase().includes(q.toLowerCase()) + (item) => + item.title.toLowerCase().includes(q.toLowerCase()) || + item.handle.toLowerCase().includes(q.toLowerCase()), ) } // Filter by status if (status.length > 0) { - filteredData = filteredData.filter(item => status.includes(item.status)) + filteredData = filteredData.filter((item) => status.includes(item.status)) } // Filter by type if (type.length > 0) { - filteredData = filteredData.filter(item => type.includes(item.type)) + filteredData = filteredData.filter((item) => type.includes(item.type)) } // Sort data if (order) { - const [field, direction] = order.startsWith('-') - ? [order.substring(1), 'desc'] + const [field, direction] = order.startsWith('-') + ? [order.substring(1), 'desc'] : [order, 'asc'] - + filteredData.sort((a, b) => { const aValue = a[field as keyof PostItem] const bValue = b[field as keyof PostItem] - + if (direction === 'asc') { return aValue > bValue ? 1 : -1 } else { @@ -91,64 +83,16 @@ const fetchPostsData = async ({ // Paginate const paginatedData = filteredData.slice(offset, offset + limit) - + // Simulate network delay - await new Promise(resolve => setTimeout(resolve, 300)) - + await new Promise((resolve) => setTimeout(resolve, 300)) + return { posts: paginatedData, count: filteredData.length, } } -// Create column helper -const columnHelper = createDataTableColumnHelper() - -// Define columns -const columns = [ - columnHelper.accessor("title", { - header: "Title", - enableSorting: true, - sortLabel: "Title", - }), - columnHelper.accessor("handle", { - header: "Handle", - enableSorting: true, - }), - columnHelper.accessor("status", { - header: "Status", - cell: ({ getValue }) => { - const status = getValue() - return ( - - {status === "published" ? "Published" : "Draft"} - - ) - }, - enableSorting: true, - }), - columnHelper.accessor("type", { - header: "Type", - enableSorting: true, - }), - columnHelper.accessor("created_at", { - header: "Date Created", - cell: ({ getValue }) => { - const date = new Date(getValue()) - return {date.toLocaleDateString()} - }, - enableSorting: true, - }), - columnHelper.accessor("updated_at", { - header: "Last Updated", - cell: ({ getValue }) => { - const date = new Date(getValue()) - return {date.toLocaleDateString()} - }, - enableSorting: true, - }), -] - // Create filter helper const filterHelper = createDataTableFilterHelper() @@ -198,17 +142,46 @@ export const PostsDataTable = () => { const offset = useMemo(() => { return pagination.pageIndex * limit }, [pagination]) + + const statusFilters = useMemo(() => { + return (filtering.status || []) as string[] + }, [filtering]) + + const typeFilters = useMemo(() => { + return (filtering.type || []) as string[] + }, [filtering]) + + const handleEdit = (post: PostItem) => { + // navigate(`/editor/${post.type}/${post.id}`) + navigate(`editor/test`) // TODO: change to the actual content detail page + } + + const handleDuplicate = (post: PostItem) => { + console.log('duplicate post', post.id) + // Implement duplication logic here + } + + const handleDelete = (post: PostItem) => { + console.log('delete post', post.id) + // Implement deletion logic here + } + + const columns = usePostsDataTableColumns({ + onEdit: handleEdit, + onDuplicate: handleDuplicate, + onDelete: handleDelete, + }) const { data, isLoading } = useQuery({ queryFn: () => fetchPostsData({ limit, offset, q: search, - status: (filtering.status || []) as string[], - type: (filtering.type || []) as string[], + status: statusFilters, + type: typeFilters, order: sorting ? `${sorting.desc ? "-" : ""}${sorting.id}` : undefined, }), - queryKey: [["posts", limit, offset, search, filtering.status, filtering.type, sorting?.id, sorting?.desc]], + queryKey: [["posts", limit, offset, search, statusFilters, typeFilters, sorting?.id, sorting?.desc]], }) const table = useDataTable({ @@ -234,19 +207,16 @@ export const PostsDataTable = () => { state: sorting, onSortingChange: setSorting, }, - onRowClick: (row) => { - navigate(`editor/test`) // TODO: change to the actual content detail page - }, }) return ( -
- +
+
- - + +
@@ -254,4 +224,4 @@ export const PostsDataTable = () => { ) -} \ No newline at end of file +} diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx new file mode 100644 index 00000000..ddf7e045 --- /dev/null +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx @@ -0,0 +1,121 @@ +import React from "react" +import { + createDataTableColumnHelper, + Badge, + Text, + StatusBadge +} from "@medusajs/ui" +import { PencilSquare, SquareTwoStackMini, Trash } from "@medusajs/icons" + +export type PostItem = { + id: string + title: string + handle: string + status: 'published' | 'draft' + type: string + created_at: string + updated_at: string +} + +export type ColumnActions = { + onEdit?: (post: PostItem) => void + onDuplicate?: (post: PostItem) => void + onDelete?: (post: PostItem) => void +} + +const columnHelper = createDataTableColumnHelper() + +/** + * Hook that returns column definitions for the PostsDataTable + */ +export const usePostsDataTableColumns = (actions: ColumnActions = {}) => { + const { onEdit, onDuplicate, onDelete } = actions + + return React.useMemo(() => [ + columnHelper.accessor("title", { + header: "Title", + enableSorting: true, + sortLabel: "Title", + }), + columnHelper.accessor("handle", { + header: "Handle", + enableSorting: true, + }), + columnHelper.accessor("status", { + header: "Status", + cell: ({ getValue }) => { + const status = getValue() + return ( + + {status === "published" ? "Published" : "Draft"} + + ) + }, + enableSorting: true, + }), + columnHelper.accessor("type", { + header: "Type", + enableSorting: true, + }), + columnHelper.accessor("created_at", { + header: "Date Created", + cell: ({ getValue }) => { + const date = new Date(getValue()) + return {date.toLocaleDateString()} + }, + enableSorting: true, + }), + columnHelper.accessor("updated_at", { + header: "Last Updated", + cell: ({ getValue }) => { + const date = new Date(getValue()) + return {date.toLocaleDateString()} + }, + enableSorting: true, + }), + columnHelper.action({ + // @ts-ignore + actions: ({ row }) => [ + [ + { + icon: , + label: 'Edit', + onClick: () => { + if (onEdit) { + onEdit(row.original) + } else { + console.log('edit', row.original.id) + } + }, + }, + ], + [ + { + icon: , + label: 'Duplicate', + onClick: () => { + if (onDuplicate) { + onDuplicate(row.original) + } else { + console.log('duplicate', row.original.id) + } + }, + }, + ], + [ + { + icon: , + label: 'Delete', + onClick: () => { + if (onDelete) { + onDelete(row.original) + } else { + console.log('delete', row.original.id) + } + }, + }, + ], + ], + }), + ], [onEdit, onDuplicate, onDelete]) +} diff --git a/plugins/page-builder/src/admin/routes/content/page.tsx b/plugins/page-builder/src/admin/routes/content/page.tsx index 0a3d1fda..e0e1780f 100644 --- a/plugins/page-builder/src/admin/routes/content/page.tsx +++ b/plugins/page-builder/src/admin/routes/content/page.tsx @@ -1,16 +1,15 @@ -import { Container } from "@medusajs/ui" +import { Button, Container } from "@medusajs/ui" import { defineRouteConfig } from "@medusajs/admin-sdk" -import { DocumentText } from "@medusajs/icons" +import { ChevronDown, DocumentText } from "@medusajs/icons" import { useNavigate } from "react-router-dom" import { SingleColumnLayout } from "../../layouts/single-column" import { Header } from "../../components/header" -import { CreatePostButton } from "./components/create-post-button" import { PostsDataTable } from "./components/posts-data-table" const ContentPage = () => { const navigate = useNavigate() - const handleCreatePost = (type: string) => { + const handleCreatePost = () => { navigate(`editor/test`) // TODO: change to the correct path // navigate(`/editor/${type}/new`) } @@ -23,13 +22,11 @@ const ContentPage = () => { actions={[ { type: "custom", - children: + children: } ]} /> -
-
) From 15eebfc1275763d13071c63fdba75f369dbe7cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Thu, 13 Mar 2025 06:16:42 -0600 Subject: [PATCH 03/28] feat(page-builder): rename models for consistency and introduce common types - Rename model exports to include 'Model' suffix for clarity (e.g., Post to PostModel). - Introduce common types for post-related entities in a new common.ts file. - Update references in the PageBuilderService and model files to use the new names. --- .../src/modules/page-builder/models/image.ts | 10 +++--- .../page-builder/models/navigation-item.ts | 2 +- .../page-builder/models/post-author.ts | 6 ++-- .../page-builder/models/post-section.ts | 10 +++--- .../modules/page-builder/models/post-tag.ts | 6 ++-- .../page-builder/models/post-template.ts | 6 ++-- .../src/modules/page-builder/models/post.ts | 27 ++++++++-------- .../page-builder/models/site-settings.ts | 6 ++-- .../src/modules/page-builder/service.ts | 32 +++++++++---------- .../src/modules/page-builder/types/common.ts | 27 ++++++++++++++++ 10 files changed, 80 insertions(+), 52 deletions(-) create mode 100644 plugins/page-builder/src/modules/page-builder/types/common.ts diff --git a/plugins/page-builder/src/modules/page-builder/models/image.ts b/plugins/page-builder/src/modules/page-builder/models/image.ts index f372a293..ab58e80a 100644 --- a/plugins/page-builder/src/modules/page-builder/models/image.ts +++ b/plugins/page-builder/src/modules/page-builder/models/image.ts @@ -1,8 +1,8 @@ import { model } from '@medusajs/framework/utils' -import { Post } from './post' -import { SiteSettings } from './site-settings' +import { PostModel } from './post' +import { SiteSettingsModel } from './site-settings' -export const Image = model +export const ImageModel = model .define('image', { id: model.id({ prefix: 'img' }).primaryKey(), url: model.text(), @@ -10,12 +10,12 @@ export const Image = model // relations fields post: model - .belongsTo(() => Post, { + .belongsTo(() => PostModel, { mappedBy: 'featured_image', }) .nullable(), site_settings: model - .belongsTo(() => SiteSettings, { + .belongsTo(() => SiteSettingsModel, { mappedBy: 'favicon', }) .nullable(), diff --git a/plugins/page-builder/src/modules/page-builder/models/navigation-item.ts b/plugins/page-builder/src/modules/page-builder/models/navigation-item.ts index 471f5db8..db55b3ab 100644 --- a/plugins/page-builder/src/modules/page-builder/models/navigation-item.ts +++ b/plugins/page-builder/src/modules/page-builder/models/navigation-item.ts @@ -1,6 +1,6 @@ import { model } from '@medusajs/framework/utils' -export const NavigationItem = model.define('navigation_item', { +export const NavigationItemModel = model.define('navigation_item', { id: model.id({ prefix: 'nav_item' }).primaryKey(), label: model.text(), location: model.enum(['header', 'footer']), diff --git a/plugins/page-builder/src/modules/page-builder/models/post-author.ts b/plugins/page-builder/src/modules/page-builder/models/post-author.ts index 00b0fbc2..f9897b73 100644 --- a/plugins/page-builder/src/modules/page-builder/models/post-author.ts +++ b/plugins/page-builder/src/modules/page-builder/models/post-author.ts @@ -1,13 +1,13 @@ import { model } from '@medusajs/framework/utils' -import { Post } from './post' +import { PostModel } from './post' -export const PostAuthor = model.define('post_author', { +export const PostAuthorModel = model.define('post_author', { id: model.id({ prefix: 'post_author' }).primaryKey(), name: model.text(), // relations fields medusa_user_id: model.text().unique(), - posts: model.manyToMany(() => Post, { + posts: model.manyToMany(() => PostModel, { mappedBy: 'authors', }), }) diff --git a/plugins/page-builder/src/modules/page-builder/models/post-section.ts b/plugins/page-builder/src/modules/page-builder/models/post-section.ts index eae96fe6..1a9823f3 100644 --- a/plugins/page-builder/src/modules/page-builder/models/post-section.ts +++ b/plugins/page-builder/src/modules/page-builder/models/post-section.ts @@ -1,8 +1,8 @@ import { model } from '@medusajs/framework/utils' -import { Post } from './post' -import { PostTemplate } from './post-template' +import { PostModel } from './post' +import { PostTemplateModel } from './post-template' -export const PostSection = model.define('post_section', { +export const PostSectionModel = model.define('post_section', { id: model.id({ prefix: 'postsec' }).primaryKey(), type: model.enum([ 'button_list', @@ -27,12 +27,12 @@ export const PostSection = model.define('post_section', { // relations fields post: model - .belongsTo(() => Post, { + .belongsTo(() => PostModel, { mappedBy: 'sections', }) .nullable(), post_template: model - .belongsTo(() => PostTemplate, { + .belongsTo(() => PostTemplateModel, { mappedBy: 'sections', }) .nullable(), diff --git a/plugins/page-builder/src/modules/page-builder/models/post-tag.ts b/plugins/page-builder/src/modules/page-builder/models/post-tag.ts index 582276d9..17e5e6c3 100644 --- a/plugins/page-builder/src/modules/page-builder/models/post-tag.ts +++ b/plugins/page-builder/src/modules/page-builder/models/post-tag.ts @@ -1,7 +1,7 @@ import { model } from '@medusajs/framework/utils' -import { Post } from './post' +import { PostModel } from './post' -export const PostTag = model.define('post_tag', { +export const PostTagModel = model.define('post_tag', { id: model.id({ prefix: 'post_tag' }).primaryKey(), label: model.text(), handle: model.text().unique(), @@ -9,7 +9,7 @@ export const PostTag = model.define('post_tag', { // relations fields created_by_id: model.text(), - posts: model.manyToMany(() => Post, { + posts: model.manyToMany(() => PostModel, { mappedBy: 'tags', }), }) diff --git a/plugins/page-builder/src/modules/page-builder/models/post-template.ts b/plugins/page-builder/src/modules/page-builder/models/post-template.ts index 5ab7a7d4..bc312b53 100644 --- a/plugins/page-builder/src/modules/page-builder/models/post-template.ts +++ b/plugins/page-builder/src/modules/page-builder/models/post-template.ts @@ -1,7 +1,7 @@ import { model } from '@medusajs/framework/utils' -import { PostSection } from './post-section' +import { PostSectionModel } from './post-section' -export const PostTemplate = model.define('post_template', { +export const PostTemplateModel = model.define('post_template', { id: model.id({ prefix: 'post_temp' }).primaryKey(), title: model.text(), status: model.enum(['draft', 'published', 'archived']).default('draft'), @@ -10,5 +10,5 @@ export const PostTemplate = model.define('post_template', { sort_order: model.number().default(0), // relations fields - sections: model.hasMany(() => PostSection), + sections: model.hasMany(() => PostSectionModel), }) diff --git a/plugins/page-builder/src/modules/page-builder/models/post.ts b/plugins/page-builder/src/modules/page-builder/models/post.ts index 0844912c..abf94a38 100644 --- a/plugins/page-builder/src/modules/page-builder/models/post.ts +++ b/plugins/page-builder/src/modules/page-builder/models/post.ts @@ -1,36 +1,37 @@ import { model } from '@medusajs/framework/utils' -import { PostSection } from './post-section' -import { PostTag } from './post-tag' -import { PostAuthor } from './post-author' -import { Image } from './image' +import { PostSectionModel } from './post-section' +import { PostTagModel } from './post-tag' +import { PostAuthorModel } from './post-author' +import { ImageModel } from './image' +import { postContentModes, postStatuses, postTypes } from '../types/common' -export const Post = model.define('post', { +export const PostModel = model.define('post', { id: model.id({ prefix: 'post' }).primaryKey(), - type: model.enum(['page', 'post']), + type: model.enum([...postTypes]), title: model.text(), handle: model.text().unique(), excerpt: model.text().nullable(), content: model.json().nullable(), - status: model.enum(['draft', 'published', 'archived']).default('draft'), - content_mode: model.enum(['basic', 'advanced']), + status: model.enum([...postStatuses]).default('draft'), + content_mode: model.enum([...postContentModes]).default('advanced'), seo: model.json().nullable(), published_at: model.text().nullable(), archived_at: model.text().nullable(), is_home_page: model.boolean().default(false), // relations fields - featured_image: model.hasOne(() => Image, { + featured_image: model.hasOne(() => ImageModel, { mappedBy: 'post', }), - authors: model.manyToMany(() => PostAuthor, { + authors: model.manyToMany(() => PostAuthorModel, { mappedBy: 'posts', }), - root: model.belongsTo(() => Post).nullable(), + root: model.belongsTo(() => PostModel).nullable(), - sections: model.hasMany(() => PostSection), + sections: model.hasMany(() => PostSectionModel), - tags: model.manyToMany(() => PostTag, { + tags: model.manyToMany(() => PostTagModel, { mappedBy: 'posts', }), }) diff --git a/plugins/page-builder/src/modules/page-builder/models/site-settings.ts b/plugins/page-builder/src/modules/page-builder/models/site-settings.ts index 461fb055..8f97c169 100644 --- a/plugins/page-builder/src/modules/page-builder/models/site-settings.ts +++ b/plugins/page-builder/src/modules/page-builder/models/site-settings.ts @@ -1,7 +1,7 @@ import { model } from '@medusajs/framework/utils' -import { Image } from './image' +import { ImageModel } from './image' -export const SiteSettings = model.define('site_settings', { +export const SiteSettingsModel = model.define('site_settings', { id: model.id({ prefix: 'site_sett' }).primaryKey(), description: model.text().nullable(), header_code: model.text().nullable(), @@ -26,7 +26,7 @@ export const SiteSettings = model.define('site_settings', { shipping_sort: model.text().nullable(), // relations - favicon: model.hasOne(() => Image, { + favicon: model.hasOne(() => ImageModel, { mappedBy: 'site_settings', }), }) diff --git a/plugins/page-builder/src/modules/page-builder/service.ts b/plugins/page-builder/src/modules/page-builder/service.ts index 46dac9fb..fef52e9b 100644 --- a/plugins/page-builder/src/modules/page-builder/service.ts +++ b/plugins/page-builder/src/modules/page-builder/service.ts @@ -1,24 +1,24 @@ import { MedusaService } from '@medusajs/framework/utils' import { - PostAuthor, - Post, - PostTemplate, - PostTag, - PostSection, - Image, - SiteSettings, - NavigationItem, + PostAuthorModel, + PostModel, + PostTemplateModel, + PostTagModel, + PostSectionModel, + ImageModel, + SiteSettingsModel, + NavigationItemModel, } from './models' class PageBuilderService extends MedusaService({ - PostAuthor, - Post, - PostTemplate, - PostTag, - PostSection, - Image, - SiteSettings, - NavigationItem, + PostAuthor: PostAuthorModel, + Post: PostModel, + PostTemplate: PostTemplateModel, + PostTag: PostTagModel, + PostSection: PostSectionModel, + Image: ImageModel, + SiteSettings: SiteSettingsModel, + NavigationItem: NavigationItemModel, }) {} export default PageBuilderService diff --git a/plugins/page-builder/src/modules/page-builder/types/common.ts b/plugins/page-builder/src/modules/page-builder/types/common.ts new file mode 100644 index 00000000..5244df11 --- /dev/null +++ b/plugins/page-builder/src/modules/page-builder/types/common.ts @@ -0,0 +1,27 @@ +import type { InferTypeOf } from '@medusajs/framework/types' + +import { PostModel } from '../models/post' +import { PostAuthorModel } from '../models/post-author' +import { PostTagModel } from '../models/post-tag' +import { PostSectionModel } from '../models/post-section' +import { PostTemplateModel } from '../models/post-template' +import { ImageModel } from '../models/image' +import { SiteSettingsModel } from '../models/site-settings' +import { NavigationItemModel } from '../models/navigation-item' + +export const postTypes = ['page', 'post'] as const +export const postStatuses = ['draft', 'published', 'archived'] as const +export const postContentModes = ['basic', 'advanced'] as const + +export type PostType = (typeof postTypes)[number] +export type PostStatus = (typeof postStatuses)[number] +export type PostContentMode = (typeof postContentModes)[number] + +export type Post = InferTypeOf +export type PostAuthor = InferTypeOf +export type PostTag = InferTypeOf +export type PostSection = InferTypeOf +export type PostTemplate = InferTypeOf +export type Image = InferTypeOf +export type SiteSettings = InferTypeOf +export type NavigationItem = InferTypeOf From 0395d14ce9b2dcfa732af3e950b4c1ca1d8aea26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Thu, 13 Mar 2025 06:17:55 -0600 Subject: [PATCH 04/28] feat(page-builder): add pageBuilderModuleEvents for post creation events - Introduce pageBuilderModuleEvents with a POST_CREATED event for better event handling. - Ensure PageBuilderService is imported for module functionality. --- plugins/page-builder/src/modules/page-builder/index.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/page-builder/src/modules/page-builder/index.ts b/plugins/page-builder/src/modules/page-builder/index.ts index 15a80ff4..2ec54443 100644 --- a/plugins/page-builder/src/modules/page-builder/index.ts +++ b/plugins/page-builder/src/modules/page-builder/index.ts @@ -1,8 +1,13 @@ -import PageBuilderService from './service' import { Module } from '@medusajs/framework/utils' +import PageBuilderService from './service' + export const PAGE_BUILDER_MODULE = 'page-builder' +export const pageBuilderModuleEvents = Object.freeze({ + POST_CREATED: 'post.created', +}) + export default Module(PAGE_BUILDER_MODULE, { service: PageBuilderService, }) From b07d71bd4eab8f46110eebed165f9c6d3e5a57a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Thu, 13 Mar 2025 10:05:09 -0600 Subject: [PATCH 05/28] feat(page-builder): update post model and migration for handle column - Change handle column to be nullable in the PostModel. - Add migration to alter handle column type and drop not null constraint. - Update snapshot to reflect changes in the database schema. --- .../migrations/.snapshot-medusa-page-builder.json | 3 ++- .../migrations/Migration20250313155933.ts | 15 +++++++++++++++ .../src/modules/page-builder/models/post.ts | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 plugins/page-builder/src/modules/page-builder/migrations/Migration20250313155933.ts diff --git a/plugins/page-builder/src/modules/page-builder/migrations/.snapshot-medusa-page-builder.json b/plugins/page-builder/src/modules/page-builder/migrations/.snapshot-medusa-page-builder.json index 7954db7b..66eeab37 100644 --- a/plugins/page-builder/src/modules/page-builder/migrations/.snapshot-medusa-page-builder.json +++ b/plugins/page-builder/src/modules/page-builder/migrations/.snapshot-medusa-page-builder.json @@ -165,7 +165,7 @@ "unsigned": false, "autoincrement": false, "primary": false, - "nullable": false, + "nullable": true, "mappedType": "text" }, "excerpt": { @@ -208,6 +208,7 @@ "autoincrement": false, "primary": false, "nullable": false, + "default": "'advanced'", "enumItems": [ "basic", "advanced" diff --git a/plugins/page-builder/src/modules/page-builder/migrations/Migration20250313155933.ts b/plugins/page-builder/src/modules/page-builder/migrations/Migration20250313155933.ts new file mode 100644 index 00000000..4016e27f --- /dev/null +++ b/plugins/page-builder/src/modules/page-builder/migrations/Migration20250313155933.ts @@ -0,0 +1,15 @@ +import { Migration } from '@mikro-orm/migrations'; + +export class Migration20250313155933 extends Migration { + + override async up(): Promise { + this.addSql(`alter table if exists "post" alter column "handle" type text using ("handle"::text);`); + this.addSql(`alter table if exists "post" alter column "handle" drop not null;`); + } + + override async down(): Promise { + this.addSql(`alter table if exists "post" alter column "handle" type text using ("handle"::text);`); + this.addSql(`alter table if exists "post" alter column "handle" set not null;`); + } + +} diff --git a/plugins/page-builder/src/modules/page-builder/models/post.ts b/plugins/page-builder/src/modules/page-builder/models/post.ts index abf94a38..8f100e09 100644 --- a/plugins/page-builder/src/modules/page-builder/models/post.ts +++ b/plugins/page-builder/src/modules/page-builder/models/post.ts @@ -9,7 +9,7 @@ export const PostModel = model.define('post', { id: model.id({ prefix: 'post' }).primaryKey(), type: model.enum([...postTypes]), title: model.text(), - handle: model.text().unique(), + handle: model.text().unique().nullable(), excerpt: model.text().nullable(), content: model.json().nullable(), status: model.enum([...postStatuses]).default('draft'), From 900e7f323a888147613aa169d9c6308ddec697e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Thu, 13 Mar 2025 10:17:19 -0600 Subject: [PATCH 06/28] feat(page-builder): implement create post workflow and related types - Add types for post creation in mutations.ts. - Create createPostWorkflow to handle post creation logic. - Implement createPostStep for managing post creation and deletion. - Export common types and mutations from index.ts for better modularity. --- .../src/modules/page-builder/types/index.ts | 2 ++ .../modules/page-builder/types/mutations.ts | 24 +++++++++++++ .../page-builder/src/workflows/create-post.ts | 24 +++++++++++++ .../src/workflows/steps/create-post.ts | 36 +++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 plugins/page-builder/src/modules/page-builder/types/index.ts create mode 100644 plugins/page-builder/src/modules/page-builder/types/mutations.ts create mode 100644 plugins/page-builder/src/workflows/create-post.ts create mode 100644 plugins/page-builder/src/workflows/steps/create-post.ts diff --git a/plugins/page-builder/src/modules/page-builder/types/index.ts b/plugins/page-builder/src/modules/page-builder/types/index.ts new file mode 100644 index 00000000..a2ab5bce --- /dev/null +++ b/plugins/page-builder/src/modules/page-builder/types/index.ts @@ -0,0 +1,2 @@ +export * from './common' +export * from './mutations' diff --git a/plugins/page-builder/src/modules/page-builder/types/mutations.ts b/plugins/page-builder/src/modules/page-builder/types/mutations.ts new file mode 100644 index 00000000..73082ac3 --- /dev/null +++ b/plugins/page-builder/src/modules/page-builder/types/mutations.ts @@ -0,0 +1,24 @@ +import type { Post, Image } from './common' + +type PostInput = Omit< + Post, + | 'id' + | 'created_at' + | 'updated_at' + | 'featured_image' + | 'root' + | 'sections' + | 'authors' + | 'tags' +> + +// Post types +export type CreatePostStepInput = Partial & { + featured_image_id?: string + authors?: string[] + tags?: string[] +} + +export type CreatePostWorkflowInput = { + post: CreatePostStepInput +} diff --git a/plugins/page-builder/src/workflows/create-post.ts b/plugins/page-builder/src/workflows/create-post.ts new file mode 100644 index 00000000..bf43cf71 --- /dev/null +++ b/plugins/page-builder/src/workflows/create-post.ts @@ -0,0 +1,24 @@ +import { transform } from '@medusajs/framework/workflows-sdk' +import { emitEventStep } from '@medusajs/medusa/core-flows' +import { WorkflowResponse, createWorkflow } from '@medusajs/workflows-sdk' +import { pageBuilderModuleEvents } from '../modules/page-builder' +import { CreatePostWorkflowInput } from '../modules/page-builder/types' +import { createPostStep } from './steps/create-post' + +export const createPostWorkflow = createWorkflow( + 'create-post-workflow', + (input: CreatePostWorkflowInput) => { + const post = createPostStep(input.post) + + const emitData = transform({ post }, ({ post }) => { + return { + eventName: pageBuilderModuleEvents.POST_CREATED, + data: { id: post.id }, + } + }) + + emitEventStep(emitData) + + return new WorkflowResponse(post) + }, +) diff --git a/plugins/page-builder/src/workflows/steps/create-post.ts b/plugins/page-builder/src/workflows/steps/create-post.ts new file mode 100644 index 00000000..fb554bcd --- /dev/null +++ b/plugins/page-builder/src/workflows/steps/create-post.ts @@ -0,0 +1,36 @@ +import { StepResponse, createStep } from '@medusajs/workflows-sdk' +import { PAGE_BUILDER_MODULE } from '../../modules/page-builder' +import type PageBuilderService from '../../modules/page-builder/service' +import type { CreatePostStepInput } from '../../modules/page-builder/types' + +export const createPostStepId = 'create-post-step' + +export const createPostStep = createStep( + createPostStepId, + async (data: CreatePostStepInput, { container }) => { + const pageBuilderService = + container.resolve(PAGE_BUILDER_MODULE) + + const createData: CreatePostStepInput = { + ...data, + status: data.status || 'draft', + content_mode: data.content_mode || 'advanced', + } + + const post = await pageBuilderService.createPosts(createData) + + return new StepResponse(post, { + postId: post.id, + }) + }, + async (data, { container }) => { + if (!data) return + + const { postId } = data + + const pageBuilderService = + container.resolve(PAGE_BUILDER_MODULE) + + await pageBuilderService.deletePosts(postId) + }, +) From 1d0f0d6a0580081301e5744c4f814e0bcd61107c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Thu, 13 Mar 2025 10:18:55 -0600 Subject: [PATCH 07/28] feat(page-builder): add admin post routes and middlewares - Implement middlewares for creating and listing posts in the admin section. - Define schemas for post creation and query validation using Zod. - Create route handlers for GET and POST requests to manage posts. - Remove obsolete admin pages route file. --- .../api/admin/content/posts/middlewares.ts | 100 ++++++++++++++++++ .../src/api/admin/content/posts/route.ts | 41 +++++++ .../page-builder/src/api/admin/pages/route.ts | 14 --- plugins/page-builder/src/api/middlewares.ts | 11 ++ 4 files changed, 152 insertions(+), 14 deletions(-) create mode 100644 plugins/page-builder/src/api/admin/content/posts/middlewares.ts create mode 100644 plugins/page-builder/src/api/admin/content/posts/route.ts delete mode 100644 plugins/page-builder/src/api/admin/pages/route.ts create mode 100644 plugins/page-builder/src/api/middlewares.ts diff --git a/plugins/page-builder/src/api/admin/content/posts/middlewares.ts b/plugins/page-builder/src/api/admin/content/posts/middlewares.ts new file mode 100644 index 00000000..f2937c52 --- /dev/null +++ b/plugins/page-builder/src/api/admin/content/posts/middlewares.ts @@ -0,0 +1,100 @@ +import { z } from 'zod' +import { + type MiddlewareRoute, + validateAndTransformQuery, + validateAndTransformBody, +} from '@medusajs/framework' +import { + createFindParams, + createOperatorMap, +} from '@medusajs/medusa/api/utils/validators' + +import { + postContentModes, + postStatuses, + postTypes, +} from '../../../../modules/page-builder/types' + +const statuses = z.enum([...postStatuses]) +const types = z.enum([...postTypes]) +const contentModes = z.enum([...postContentModes]) + +export const createPostSchema = z.object({ + title: z.string(), + handle: z.string().optional(), + excerpt: z.string().optional(), + content: z.record(z.string(), z.any()).optional(), + status: statuses.optional(), + type: types.optional(), + content_mode: contentModes.optional(), + seo: z.record(z.string(), z.any()).optional(), + is_home_page: z.boolean().optional(), +}) + +export type CreatePostDTO = z.infer + +export const listAdminPostsQuerySchema = createFindParams({ + offset: 0, + limit: 50, +}).merge( + z.object({ + q: z.string().optional(), + id: z.union([z.string(), z.array(z.string())]).optional(), + title: z.string().optional(), + handle: z.string().optional(), + status: z.union([statuses, z.array(statuses)]).optional(), + type: z.union([types, z.array(types)]).optional(), + content_mode: z.union([contentModes, z.array(contentModes)]).optional(), + is_home_page: z.boolean().optional(), + published_at: createOperatorMap().optional(), + archived_at: createOperatorMap().optional(), + created_at: createOperatorMap().optional(), + updated_at: createOperatorMap().optional(), + }), +) + +export const defaultAdminPostFields = [ + 'id', + 'type', + 'title', + 'handle', + 'excerpt', + 'content', + 'status', + 'content_mode', + 'seo', + 'published_at', + 'archived_at', + 'is_home_page', + 'created_at', + 'updated_at', + 'featured_image.*', + 'authors.*', + 'root.*', + 'sections.*', + 'tags.*', +] + +export const defaultPostsQueryConfig = { + defaults: [...defaultAdminPostFields], + defaultLimit: 50, + isList: true, +} + +export const adminPostRoutesMiddlewares: MiddlewareRoute[] = [ + { + matcher: '/admin/content/posts', + method: 'GET', + middlewares: [ + validateAndTransformQuery( + listAdminPostsQuerySchema, + defaultPostsQueryConfig, + ), + ], + }, + { + matcher: '/admin/content/posts', + method: 'POST', + middlewares: [validateAndTransformBody(createPostSchema)], + }, +] diff --git a/plugins/page-builder/src/api/admin/content/posts/route.ts b/plugins/page-builder/src/api/admin/content/posts/route.ts new file mode 100644 index 00000000..e97849d4 --- /dev/null +++ b/plugins/page-builder/src/api/admin/content/posts/route.ts @@ -0,0 +1,41 @@ +import { + AuthenticatedMedusaRequest, + MedusaResponse, +} from '@medusajs/framework/http' +import { createPostWorkflow } from '../../../../workflows/create-post' +import { CreatePostDTO } from './middlewares' + +export const GET = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse, +) => { + const query = req.scope.resolve('query') + + const { data: posts, metadata = { count: 0, skip: 0, take: 0 } } = + await query.graph({ + entity: 'post', + fields: req.queryConfig?.fields || ['*'], + filters: req.filterableFields || {}, + pagination: req.queryConfig?.pagination || { skip: 0, take: 10 }, + }) + + res.status(200).json({ + posts: posts, + count: metadata.count, + offset: metadata.skip, + limit: metadata.take, + }) +} + +export const POST = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse, +) => { + const { result } = await createPostWorkflow(req.scope).run({ + input: { + post: req.validatedBody, + }, + }) + + res.status(200).json({ post: result }) +} diff --git a/plugins/page-builder/src/api/admin/pages/route.ts b/plugins/page-builder/src/api/admin/pages/route.ts deleted file mode 100644 index 6dbb0f27..00000000 --- a/plugins/page-builder/src/api/admin/pages/route.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { - AuthenticatedMedusaRequest, - MedusaResponse, -} from '@medusajs/framework/http' - -export const GET = async ( - req: AuthenticatedMedusaRequest, - res: MedusaResponse, -) => { - res.json({ - success: true, - message: 'Page Builder API is working!!', - }) -} diff --git a/plugins/page-builder/src/api/middlewares.ts b/plugins/page-builder/src/api/middlewares.ts new file mode 100644 index 00000000..5912884b --- /dev/null +++ b/plugins/page-builder/src/api/middlewares.ts @@ -0,0 +1,11 @@ +import { defineMiddlewares } from '@medusajs/medusa' +import { adminPostRoutesMiddlewares } from './admin/content/posts/middlewares' + +export default defineMiddlewares({ + routes: [ + // Admin + ...adminPostRoutesMiddlewares, + + // Store + ], +}) From 41c70acefa75d3b999f338c6be8382f62ef37c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Thu, 13 Mar 2025 10:20:34 -0600 Subject: [PATCH 08/28] feat(page-builder): implement ExtendedMedusaSDK and resource classes - Introduce ExtendedMedusaSDK to encapsulate admin and store resources. - Create AdminPageBuilderResource for managing admin post operations. - Implement ExtendedAdmin and ExtendedStore classes to extend Medusa functionality. - Define types for admin page builder operations in types.ts. - Establish StorePageBuilderResource for future store-related functionalities. --- .../src/sdk/admin/admin-page-builder.ts | 31 +++++++++++++++++++ plugins/page-builder/src/sdk/admin/index.ts | 13 ++++++++ plugins/page-builder/src/sdk/index.ts | 18 +++++++++++ plugins/page-builder/src/sdk/store/index.ts | 13 ++++++++ .../src/sdk/store/store-page-builder.ts | 11 +++++++ plugins/page-builder/src/sdk/types.ts | 27 ++++++++++++++++ 6 files changed, 113 insertions(+) create mode 100644 plugins/page-builder/src/sdk/admin/admin-page-builder.ts create mode 100644 plugins/page-builder/src/sdk/admin/index.ts create mode 100644 plugins/page-builder/src/sdk/index.ts create mode 100644 plugins/page-builder/src/sdk/store/index.ts create mode 100644 plugins/page-builder/src/sdk/store/store-page-builder.ts create mode 100644 plugins/page-builder/src/sdk/types.ts diff --git a/plugins/page-builder/src/sdk/admin/admin-page-builder.ts b/plugins/page-builder/src/sdk/admin/admin-page-builder.ts new file mode 100644 index 00000000..52553faf --- /dev/null +++ b/plugins/page-builder/src/sdk/admin/admin-page-builder.ts @@ -0,0 +1,31 @@ +import type { Client } from '@medusajs/js-sdk' +import type { + AdminPageBuilderCreatePostBody, + AdminPageBuilderCreatePostResponse, + AdminPageBuilderListPostsQuery, + AdminPageBuilderListPostsResponse, +} from '../types' + +export class AdminPageBuilderResource { + constructor(private client: Client) {} + + async listPosts(query: AdminPageBuilderListPostsQuery) { + return this.client.fetch( + `/admin/content/posts`, + { + method: 'GET', + query, + }, + ) + } + + async createPost(data: AdminPageBuilderCreatePostBody) { + return this.client.fetch( + `/admin/content/posts`, + { + method: 'POST', + body: data, + }, + ) + } +} diff --git a/plugins/page-builder/src/sdk/admin/index.ts b/plugins/page-builder/src/sdk/admin/index.ts new file mode 100644 index 00000000..fee272db --- /dev/null +++ b/plugins/page-builder/src/sdk/admin/index.ts @@ -0,0 +1,13 @@ +import type { Client } from '@medusajs/js-sdk' +import { Admin as MedusaAdmin } from '@medusajs/js-sdk' +import { AdminPageBuilderResource } from './admin-page-builder' + +export class ExtendedAdmin extends MedusaAdmin { + public pageBuilder: AdminPageBuilderResource + + constructor(client: Client) { + super(client) + + this.pageBuilder = new AdminPageBuilderResource(client) + } +} diff --git a/plugins/page-builder/src/sdk/index.ts b/plugins/page-builder/src/sdk/index.ts new file mode 100644 index 00000000..532afb74 --- /dev/null +++ b/plugins/page-builder/src/sdk/index.ts @@ -0,0 +1,18 @@ +import Medusa, { type Config } from '@medusajs/js-sdk' +import { ExtendedAdmin } from './admin' +import { ExtendedStore } from './store' + +export class ExtendedMedusaSDK extends Medusa { + public admin: ExtendedAdmin + public store: ExtendedStore + + constructor(config: Config) { + super(config) + + this.admin = new ExtendedAdmin(this.client) + this.store = new ExtendedStore(this.client) + } +} + +export { AdminPageBuilderResource } from './admin/admin-page-builder' +export { StorePageBuilderResource } from './store/store-page-builder' diff --git a/plugins/page-builder/src/sdk/store/index.ts b/plugins/page-builder/src/sdk/store/index.ts new file mode 100644 index 00000000..f3965048 --- /dev/null +++ b/plugins/page-builder/src/sdk/store/index.ts @@ -0,0 +1,13 @@ +import type { Client } from '@medusajs/js-sdk' +import { Store as MedusaStore } from '@medusajs/js-sdk' +import { StorePageBuilderResource } from './store-page-builder' + +export class ExtendedStore extends MedusaStore { + public pageBuilder: StorePageBuilderResource + + constructor(client: Client) { + super(client) + + this.pageBuilder = new StorePageBuilderResource(client) + } +} diff --git a/plugins/page-builder/src/sdk/store/store-page-builder.ts b/plugins/page-builder/src/sdk/store/store-page-builder.ts new file mode 100644 index 00000000..d7e98de9 --- /dev/null +++ b/plugins/page-builder/src/sdk/store/store-page-builder.ts @@ -0,0 +1,11 @@ +import type { Client, ClientHeaders } from '@medusajs/js-sdk' + +export class StorePageBuilderResource { + constructor(private client: Client) {} + + // async getPost(postId: string) { + // return this.client.fetch(`/store/content/posts/${postId}`, { + // method: 'GET', + // }); + // } +} diff --git a/plugins/page-builder/src/sdk/types.ts b/plugins/page-builder/src/sdk/types.ts new file mode 100644 index 00000000..5232cf60 --- /dev/null +++ b/plugins/page-builder/src/sdk/types.ts @@ -0,0 +1,27 @@ +import { z } from 'zod' + +import { Post } from '../modules/page-builder/types' +import { + CreatePostDTO, + listAdminPostsQuerySchema, +} from '../api/admin/content/posts/middlewares' + +interface PaginatedResponse { + count: number + offset: number + limit: number +} + +export type AdminPageBuilderListPostsQuery = z.infer< + typeof listAdminPostsQuerySchema +> + +export interface AdminPageBuilderListPostsResponse extends PaginatedResponse { + posts: Post[] +} + +export type AdminPageBuilderCreatePostBody = CreatePostDTO + +export type AdminPageBuilderCreatePostResponse = { + post: Post +} From 16469e80f3e2be09c9f65f1bcb1003460a8b3a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Thu, 13 Mar 2025 10:21:00 -0600 Subject: [PATCH 09/28] feat(page-builder): add sdk.ts for ExtendedMedusaSDK initialization - Create sdk.ts to initialize ExtendedMedusaSDK with backend URL configuration. --- plugins/page-builder/src/admin/sdk.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 plugins/page-builder/src/admin/sdk.ts diff --git a/plugins/page-builder/src/admin/sdk.ts b/plugins/page-builder/src/admin/sdk.ts new file mode 100644 index 00000000..11ed87df --- /dev/null +++ b/plugins/page-builder/src/admin/sdk.ts @@ -0,0 +1,12 @@ +import { ExtendedMedusaSDK } from '../sdk' + +declare const __BACKEND_URL__: string | undefined + +export const backendUrl = __BACKEND_URL__ ?? 'http://localhost:9000' + +export const sdk = new ExtendedMedusaSDK({ + baseUrl: backendUrl, + auth: { + type: 'session', + }, +}) From 3b6ad249eb1b25fb6dd88adc8af8b8909e221bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Thu, 13 Mar 2025 10:21:49 -0600 Subject: [PATCH 10/28] fix(page-builder): replace fragment shorthand with Fragment component in Header - Update Header component to use Fragment for better key management in action mapping. - Ensure consistent usage of React components for improved readability. --- plugins/page-builder/src/admin/components/header.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/page-builder/src/admin/components/header.tsx b/plugins/page-builder/src/admin/components/header.tsx index 1d51d8be..253b44bc 100644 --- a/plugins/page-builder/src/admin/components/header.tsx +++ b/plugins/page-builder/src/admin/components/header.tsx @@ -1,5 +1,5 @@ import { Heading, Button, Text } from "@medusajs/ui" -import React from "react" +import React, { Fragment } from "react" import { Link, LinkProps } from "react-router-dom" import { ActionMenu, ActionMenuProps } from "./action-menu" @@ -41,12 +41,11 @@ export const Header = ({ {actions.length > 0 && (
{actions.map((action, index) => ( - <> + {action.type === "button" && (
)} From 3988c992ac55eeb17a00dd30161712deae2eac5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Thu, 13 Mar 2025 10:24:58 -0600 Subject: [PATCH 11/28] feat(page-builder): implement post creation and listing hooks - Add useAdminCreatePost hook for creating posts with mutation handling. - Introduce useAdminListPosts and useAdminFetchPost hooks for fetching posts and individual post details. - Update ContentPage to utilize the new post creation hook and manage loading state. - Refactor PostsDataTable to use the new admin hooks for data fetching and filtering. - Enhance type definitions for better clarity and consistency across components. --- .../src/admin/hooks/posts-mutations.ts | 25 ++++ .../src/admin/hooks/posts-queries.ts | 36 ++++++ .../components/posts-data-table/index.tsx | 116 +++--------------- .../use-posts-data-table-columns.tsx | 19 +-- .../src/admin/routes/content/page.tsx | 15 ++- 5 files changed, 94 insertions(+), 117 deletions(-) create mode 100644 plugins/page-builder/src/admin/hooks/posts-mutations.ts create mode 100644 plugins/page-builder/src/admin/hooks/posts-queries.ts diff --git a/plugins/page-builder/src/admin/hooks/posts-mutations.ts b/plugins/page-builder/src/admin/hooks/posts-mutations.ts new file mode 100644 index 00000000..5789726c --- /dev/null +++ b/plugins/page-builder/src/admin/hooks/posts-mutations.ts @@ -0,0 +1,25 @@ +import { useMutation, useQueryClient } from '@tanstack/react-query' +import { sdk } from '../sdk' +import { + AdminPageBuilderCreatePostBody, + AdminPageBuilderCreatePostResponse, +} from '../../sdk/types' + +const QUERY_KEY = ['posts'] + +export const useAdminCreatePost = () => { + const queryClient = useQueryClient() + return useMutation< + AdminPageBuilderCreatePostResponse, + Error, + AdminPageBuilderCreatePostBody + >({ + mutationFn: async (data) => { + return sdk.admin.pageBuilder.createPost(data) + }, + mutationKey: QUERY_KEY, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: QUERY_KEY }) + }, + }) +} diff --git a/plugins/page-builder/src/admin/hooks/posts-queries.ts b/plugins/page-builder/src/admin/hooks/posts-queries.ts new file mode 100644 index 00000000..1eee063a --- /dev/null +++ b/plugins/page-builder/src/admin/hooks/posts-queries.ts @@ -0,0 +1,36 @@ +import { useQuery } from '@tanstack/react-query' + +import { sdk } from '../sdk' +import { + AdminPageBuilderListPostsQuery, + AdminPageBuilderListPostsResponse, +} from '../../sdk/types' + +import { Post } from '../../modules/page-builder/types' + +const QUERY_KEY = ['posts'] + +export const useAdminListPosts = (query: AdminPageBuilderListPostsQuery) => { + return useQuery< + AdminPageBuilderListPostsResponse, + AdminPageBuilderListPostsQuery + >({ + queryKey: [...QUERY_KEY, query], + queryFn: async () => { + return sdk.admin.pageBuilder.listPosts(query) + }, + }) +} + +export const useAdminFetchPost = (id: string) => { + return useQuery({ + queryKey: [...QUERY_KEY, id], + queryFn: async () => { + const post = await sdk.admin.pageBuilder.listPosts({ + id, + } as AdminPageBuilderListPostsQuery) + + return post?.posts?.[0] + }, + }) +} diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx index a01bf97e..19105895 100644 --- a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx @@ -6,95 +6,14 @@ import { DataTableSortingState, useDataTable, } from '@medusajs/ui' -import { useQuery } from '@tanstack/react-query' import { useMemo, useState } from 'react' import { useNavigate } from 'react-router-dom' -import { PostItem, usePostsDataTableColumns } from './use-posts-data-table-columns' - -// Mock data function - this would be replaced with actual API calls later -const fetchPostsData = async ({ - limit = 10, - offset = 0, - q = '', - status = [], - type = [], - order, -}: { - limit?: number - offset?: number - q?: string - status?: string[] - type?: string[] - order?: string -}) => { - // Mock data - const allData: PostItem[] = Array(30) - .fill(null) - .map((_, i) => { - const type = i % 2 === 0 ? 'post' : 'page' - return { - id: `${type}-${i + 1}`, - title: `${type.charAt(0).toUpperCase() + type.slice(1)} ${i + 1}`, - handle: `${type}-${i + 1}`, - status: i % 3 === 0 ? 'published' : 'draft', - type: type, - created_at: new Date(Date.now() - i * 86400000).toISOString(), - updated_at: new Date(Date.now() - i * 43200000).toISOString(), - } - }) - - // Filter by search term - let filteredData = allData - if (q) { - filteredData = filteredData.filter( - (item) => - item.title.toLowerCase().includes(q.toLowerCase()) || - item.handle.toLowerCase().includes(q.toLowerCase()), - ) - } - - // Filter by status - if (status.length > 0) { - filteredData = filteredData.filter((item) => status.includes(item.status)) - } - - // Filter by type - if (type.length > 0) { - filteredData = filteredData.filter((item) => type.includes(item.type)) - } - - // Sort data - if (order) { - const [field, direction] = order.startsWith('-') - ? [order.substring(1), 'desc'] - : [order, 'asc'] - - filteredData.sort((a, b) => { - const aValue = a[field as keyof PostItem] - const bValue = b[field as keyof PostItem] - - if (direction === 'asc') { - return aValue > bValue ? 1 : -1 - } else { - return aValue < bValue ? 1 : -1 - } - }) - } - - // Paginate - const paginatedData = filteredData.slice(offset, offset + limit) - - // Simulate network delay - await new Promise((resolve) => setTimeout(resolve, 300)) - - return { - posts: paginatedData, - count: filteredData.length, - } -} +import { usePostsDataTableColumns } from './use-posts-data-table-columns' +import { useAdminListPosts } from '../../../../hooks/posts-queries' +import { Post, PostStatus, PostType } from '../../../../../modules/page-builder/types' // Create filter helper -const filterHelper = createDataTableFilterHelper() +const filterHelper = createDataTableFilterHelper() // Define filters const filters = [ @@ -144,24 +63,24 @@ export const PostsDataTable = () => { }, [pagination]) const statusFilters = useMemo(() => { - return (filtering.status || []) as string[] + return (filtering.status || []) as PostStatus[] }, [filtering]) const typeFilters = useMemo(() => { - return (filtering.type || []) as string[] + return (filtering.type || []) as PostType[] }, [filtering]) - const handleEdit = (post: PostItem) => { + const handleEdit = (post: Post) => { // navigate(`/editor/${post.type}/${post.id}`) navigate(`editor/test`) // TODO: change to the actual content detail page } - const handleDuplicate = (post: PostItem) => { + const handleDuplicate = (post: Post) => { console.log('duplicate post', post.id) // Implement duplication logic here } - const handleDelete = (post: PostItem) => { + const handleDelete = (post: Post) => { console.log('delete post', post.id) // Implement deletion logic here } @@ -172,16 +91,13 @@ export const PostsDataTable = () => { onDelete: handleDelete, }) - const { data, isLoading } = useQuery({ - queryFn: () => fetchPostsData({ - limit, - offset, - q: search, - status: statusFilters, - type: typeFilters, - order: sorting ? `${sorting.desc ? "-" : ""}${sorting.id}` : undefined, - }), - queryKey: [["posts", limit, offset, search, statusFilters, typeFilters, sorting?.id, sorting?.desc]], + const { data, isLoading } = useAdminListPosts({ + limit, + offset, + q: search, + status: statusFilters, + type: typeFilters, + order: sorting ? `${sorting.desc ? "-" : ""}${sorting.id}` : undefined, }) const table = useDataTable({ diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx index ddf7e045..45d4ecab 100644 --- a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx @@ -1,29 +1,20 @@ import React from "react" import { createDataTableColumnHelper, - Badge, Text, StatusBadge } from "@medusajs/ui" import { PencilSquare, SquareTwoStackMini, Trash } from "@medusajs/icons" +import { Post } from "../../../../../modules/page-builder/types" -export type PostItem = { - id: string - title: string - handle: string - status: 'published' | 'draft' - type: string - created_at: string - updated_at: string -} export type ColumnActions = { - onEdit?: (post: PostItem) => void - onDuplicate?: (post: PostItem) => void - onDelete?: (post: PostItem) => void + onEdit?: (post: Post) => void + onDuplicate?: (post: Post) => void + onDelete?: (post: Post) => void } -const columnHelper = createDataTableColumnHelper() +const columnHelper = createDataTableColumnHelper() /** * Hook that returns column definitions for the PostsDataTable diff --git a/plugins/page-builder/src/admin/routes/content/page.tsx b/plugins/page-builder/src/admin/routes/content/page.tsx index e0e1780f..edada810 100644 --- a/plugins/page-builder/src/admin/routes/content/page.tsx +++ b/plugins/page-builder/src/admin/routes/content/page.tsx @@ -1,15 +1,24 @@ import { Button, Container } from "@medusajs/ui" import { defineRouteConfig } from "@medusajs/admin-sdk" -import { ChevronDown, DocumentText } from "@medusajs/icons" +import { DocumentText } from "@medusajs/icons" import { useNavigate } from "react-router-dom" import { SingleColumnLayout } from "../../layouts/single-column" import { Header } from "../../components/header" import { PostsDataTable } from "./components/posts-data-table" +import { useAdminCreatePost } from "../../hooks/posts-mutations" const ContentPage = () => { const navigate = useNavigate() - const handleCreatePost = () => { + const { mutateAsync: createPost, isPending } = useAdminCreatePost() + + const handleCreatePost = async () => { + await createPost({ + title: 'New Page', + content: {}, + type: 'page' + }) + navigate(`editor/test`) // TODO: change to the correct path // navigate(`/editor/${type}/new`) } @@ -22,7 +31,7 @@ const ContentPage = () => { actions={[ { type: "custom", - children: + children: } ]} /> From 09ce6596e93654620f112c3d407fea79c2210269 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Thu, 13 Mar 2025 10:57:45 -0600 Subject: [PATCH 12/28] feat(page-builder): implement post update workflow and related types - Add POST_UPDATED event to pageBuilderModuleEvents for handling post updates. - Introduce UpdatePostStepInput and UpdatePostWorkflowInput types for post update operations. - Create updatePostWorkflow to manage the update process and emit events. - Implement updatePostStep for updating posts with rollback functionality. --- .../src/modules/page-builder/index.ts | 1 + .../modules/page-builder/types/mutations.ts | 8 ++++ .../src/workflows/steps/update-post.ts | 39 +++++++++++++++++++ .../page-builder/src/workflows/update-post.ts | 25 ++++++++++++ 4 files changed, 73 insertions(+) create mode 100644 plugins/page-builder/src/workflows/steps/update-post.ts create mode 100644 plugins/page-builder/src/workflows/update-post.ts diff --git a/plugins/page-builder/src/modules/page-builder/index.ts b/plugins/page-builder/src/modules/page-builder/index.ts index 2ec54443..dd1ef37a 100644 --- a/plugins/page-builder/src/modules/page-builder/index.ts +++ b/plugins/page-builder/src/modules/page-builder/index.ts @@ -6,6 +6,7 @@ export const PAGE_BUILDER_MODULE = 'page-builder' export const pageBuilderModuleEvents = Object.freeze({ POST_CREATED: 'post.created', + POST_UPDATED: 'post.updated', }) export default Module(PAGE_BUILDER_MODULE, { diff --git a/plugins/page-builder/src/modules/page-builder/types/mutations.ts b/plugins/page-builder/src/modules/page-builder/types/mutations.ts index 73082ac3..2bd177c8 100644 --- a/plugins/page-builder/src/modules/page-builder/types/mutations.ts +++ b/plugins/page-builder/src/modules/page-builder/types/mutations.ts @@ -19,6 +19,14 @@ export type CreatePostStepInput = Partial & { tags?: string[] } +export type UpdatePostStepInput = { + id: string +} & Partial + export type CreatePostWorkflowInput = { post: CreatePostStepInput } + +export type UpdatePostWorkflowInput = { + post: UpdatePostStepInput +} diff --git a/plugins/page-builder/src/workflows/steps/update-post.ts b/plugins/page-builder/src/workflows/steps/update-post.ts new file mode 100644 index 00000000..b3cb21d0 --- /dev/null +++ b/plugins/page-builder/src/workflows/steps/update-post.ts @@ -0,0 +1,39 @@ +import { StepResponse, createStep } from '@medusajs/workflows-sdk' +import { PAGE_BUILDER_MODULE } from '../../modules/page-builder' +import type PageBuilderService from '../../modules/page-builder/service' +import type { UpdatePostStepInput } from '../../modules/page-builder/types' + +export const updatePostStepId = 'update-post-step' + +export const updatePostStep = createStep( + updatePostStepId, + async (data: UpdatePostStepInput, { container }) => { + const pageBuilderService = + container.resolve(PAGE_BUILDER_MODULE) + + // Get the existing post before updating for rollback + const existingPost = await pageBuilderService.retrievePost(data.id, { + relations: ['root', 'featured_image', 'authors', 'sections', 'tags'], + }) + + const post = await pageBuilderService.updatePosts(data) + + return new StepResponse(post, { + ...existingPost, + featured_image: existingPost.featured_image?.id, + authors: existingPost.authors.map((author) => author.id), + sections: existingPost.sections.map((section) => section.id), + tags: existingPost.tags.map((tag) => tag.id), + root: existingPost.root?.id, + }) + }, + async (existingData, { container }) => { + if (!existingData) return + + const pageBuilderService = + container.resolve(PAGE_BUILDER_MODULE) + + // Rollback to the previous state with only the updatable fields + await pageBuilderService.updatePosts(existingData) + }, +) diff --git a/plugins/page-builder/src/workflows/update-post.ts b/plugins/page-builder/src/workflows/update-post.ts new file mode 100644 index 00000000..82db3546 --- /dev/null +++ b/plugins/page-builder/src/workflows/update-post.ts @@ -0,0 +1,25 @@ +import { transform } from '@medusajs/framework/workflows-sdk' +import { emitEventStep } from '@medusajs/medusa/core-flows' +import { WorkflowResponse, createWorkflow } from '@medusajs/workflows-sdk' + +import { pageBuilderModuleEvents } from '../modules/page-builder' +import { UpdatePostWorkflowInput } from '../modules/page-builder/types' +import { updatePostStep } from './steps/update-post' + +export const updatePostWorkflow = createWorkflow( + 'update-post-workflow', + (input: UpdatePostWorkflowInput) => { + const post = updatePostStep(input.post) + + const emitData = transform({ post }, ({ post }) => { + return { + eventName: pageBuilderModuleEvents.POST_UPDATED, + data: { id: post.id }, + } + }) + + emitEventStep(emitData) + + return new WorkflowResponse(post) + }, +) From 68817017afbb1071326ca1e4f9e856e5be61e677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Thu, 13 Mar 2025 11:12:46 -0600 Subject: [PATCH 13/28] feat(page-builder): add post update functionality and related types - Introduce updatePostSchema for validating post updates. - Create UpdatePostDTO type for structured update requests. - Implement PUT route handler for updating posts using the new updatePostWorkflow. - Enhance admin post middlewares to include update functionality. --- .../api/admin/content/posts/middlewares.ts | 19 +++++++++++++++++++ .../src/api/admin/content/posts/route.ts | 16 +++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/plugins/page-builder/src/api/admin/content/posts/middlewares.ts b/plugins/page-builder/src/api/admin/content/posts/middlewares.ts index f2937c52..fe76a687 100644 --- a/plugins/page-builder/src/api/admin/content/posts/middlewares.ts +++ b/plugins/page-builder/src/api/admin/content/posts/middlewares.ts @@ -31,7 +31,21 @@ export const createPostSchema = z.object({ is_home_page: z.boolean().optional(), }) +export const updatePostSchema = z.object({ + id: z.string(), + title: z.string().optional(), + handle: z.string().optional(), + excerpt: z.string().optional(), + content: z.record(z.string(), z.any()).optional(), + status: statuses.optional(), + type: types.optional(), + content_mode: contentModes.optional(), + seo: z.record(z.string(), z.any()).optional(), + is_home_page: z.boolean().optional(), +}) + export type CreatePostDTO = z.infer +export type UpdatePostDTO = z.infer export const listAdminPostsQuerySchema = createFindParams({ offset: 0, @@ -97,4 +111,9 @@ export const adminPostRoutesMiddlewares: MiddlewareRoute[] = [ method: 'POST', middlewares: [validateAndTransformBody(createPostSchema)], }, + { + matcher: '/admin/content/posts', + method: 'PUT', + middlewares: [validateAndTransformBody(updatePostSchema)], + }, ] diff --git a/plugins/page-builder/src/api/admin/content/posts/route.ts b/plugins/page-builder/src/api/admin/content/posts/route.ts index e97849d4..7e7309f5 100644 --- a/plugins/page-builder/src/api/admin/content/posts/route.ts +++ b/plugins/page-builder/src/api/admin/content/posts/route.ts @@ -3,7 +3,8 @@ import { MedusaResponse, } from '@medusajs/framework/http' import { createPostWorkflow } from '../../../../workflows/create-post' -import { CreatePostDTO } from './middlewares' +import { updatePostWorkflow } from '../../../../workflows/update-post' +import { CreatePostDTO, UpdatePostDTO } from './middlewares' export const GET = async ( req: AuthenticatedMedusaRequest, @@ -39,3 +40,16 @@ export const POST = async ( res.status(200).json({ post: result }) } + +export const PUT = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse, +) => { + const { result } = await updatePostWorkflow(req.scope).run({ + input: { + post: req.validatedBody, + }, + }) + + res.status(200).json({ post: result }) +} From 51cfeafc10d47027b755a46ef179a92a3ea34032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Mon, 17 Mar 2025 09:24:08 -0600 Subject: [PATCH 14/28] feat(page-builder): enhance post managemen - Introduce deletePostWorkflow and deletePostStep for handling post deletions. - Add DELETE route handler for removing posts by ID. - Implement validation schemas for post creation, update, and deletion. - Refactor middlewares to include new admin post item routes. - Update pageBuilderModuleEvents to include POST_DELETED event for better event handling. --- .../admin/content/posts/[id]/middlewares.ts | 19 +++++ .../api/admin/content/posts/[id]/route.tsx | 38 ++++++++++ .../api/admin/content/posts/middlewares.ts | 68 +----------------- .../src/api/admin/content/posts/route.ts | 16 +---- .../src/api/admin/content/validations.ts | 71 +++++++++++++++++++ plugins/page-builder/src/api/middlewares.ts | 15 ++-- .../src/modules/page-builder/index.ts | 1 + .../modules/page-builder/types/mutations.ts | 9 +++ .../page-builder/src/workflows/delete-post.ts | 26 +++++++ .../src/workflows/steps/delete-post.ts | 51 +++++++++++++ .../src/workflows/steps/update-post.ts | 14 ++-- 11 files changed, 231 insertions(+), 97 deletions(-) create mode 100644 plugins/page-builder/src/api/admin/content/posts/[id]/middlewares.ts create mode 100644 plugins/page-builder/src/api/admin/content/posts/[id]/route.tsx create mode 100644 plugins/page-builder/src/api/admin/content/validations.ts create mode 100644 plugins/page-builder/src/workflows/delete-post.ts create mode 100644 plugins/page-builder/src/workflows/steps/delete-post.ts diff --git a/plugins/page-builder/src/api/admin/content/posts/[id]/middlewares.ts b/plugins/page-builder/src/api/admin/content/posts/[id]/middlewares.ts new file mode 100644 index 00000000..311f6129 --- /dev/null +++ b/plugins/page-builder/src/api/admin/content/posts/[id]/middlewares.ts @@ -0,0 +1,19 @@ +import { z } from 'zod' +import { + type MiddlewareRoute, + validateAndTransformBody, +} from '@medusajs/framework' +import { updatePostSchema } from '../../validations' + +export const adminPostItemRoutesMiddlewares: MiddlewareRoute[] = [ + { + matcher: '/admin/content/posts/:id', + method: 'PUT', + middlewares: [validateAndTransformBody(updatePostSchema)], + }, + { + matcher: '/admin/content/posts/:id', + method: 'DELETE', + middlewares: [], + }, +] diff --git a/plugins/page-builder/src/api/admin/content/posts/[id]/route.tsx b/plugins/page-builder/src/api/admin/content/posts/[id]/route.tsx new file mode 100644 index 00000000..3b98ac12 --- /dev/null +++ b/plugins/page-builder/src/api/admin/content/posts/[id]/route.tsx @@ -0,0 +1,38 @@ +import { + AuthenticatedMedusaRequest, + MedusaResponse, +} from '@medusajs/framework/http' +import { updatePostWorkflow } from '../../../../../workflows/update-post' +import { deletePostWorkflow } from '../../../../../workflows/delete-post' +import { UpdatePostDTO } from '../../validations' + +export const PUT = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse, +) => { + const id = req.params.id + const data = { ...req.validatedBody, id } + + const { result } = await updatePostWorkflow(req.scope).run({ + input: { + post: data, + }, + }) + + res.status(200).json({ post: result }) +} + +export const DELETE = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse, +) => { + const id = req.params.id + + const { result } = await deletePostWorkflow(req.scope).run({ + input: { + id, + }, + }) + + res.status(200).json({ id: result.id, object: 'post', deleted: true }) +} diff --git a/plugins/page-builder/src/api/admin/content/posts/middlewares.ts b/plugins/page-builder/src/api/admin/content/posts/middlewares.ts index fe76a687..d7c26fc1 100644 --- a/plugins/page-builder/src/api/admin/content/posts/middlewares.ts +++ b/plugins/page-builder/src/api/admin/content/posts/middlewares.ts @@ -4,68 +4,7 @@ import { validateAndTransformQuery, validateAndTransformBody, } from '@medusajs/framework' -import { - createFindParams, - createOperatorMap, -} from '@medusajs/medusa/api/utils/validators' - -import { - postContentModes, - postStatuses, - postTypes, -} from '../../../../modules/page-builder/types' - -const statuses = z.enum([...postStatuses]) -const types = z.enum([...postTypes]) -const contentModes = z.enum([...postContentModes]) - -export const createPostSchema = z.object({ - title: z.string(), - handle: z.string().optional(), - excerpt: z.string().optional(), - content: z.record(z.string(), z.any()).optional(), - status: statuses.optional(), - type: types.optional(), - content_mode: contentModes.optional(), - seo: z.record(z.string(), z.any()).optional(), - is_home_page: z.boolean().optional(), -}) - -export const updatePostSchema = z.object({ - id: z.string(), - title: z.string().optional(), - handle: z.string().optional(), - excerpt: z.string().optional(), - content: z.record(z.string(), z.any()).optional(), - status: statuses.optional(), - type: types.optional(), - content_mode: contentModes.optional(), - seo: z.record(z.string(), z.any()).optional(), - is_home_page: z.boolean().optional(), -}) - -export type CreatePostDTO = z.infer -export type UpdatePostDTO = z.infer - -export const listAdminPostsQuerySchema = createFindParams({ - offset: 0, - limit: 50, -}).merge( - z.object({ - q: z.string().optional(), - id: z.union([z.string(), z.array(z.string())]).optional(), - title: z.string().optional(), - handle: z.string().optional(), - status: z.union([statuses, z.array(statuses)]).optional(), - type: z.union([types, z.array(types)]).optional(), - content_mode: z.union([contentModes, z.array(contentModes)]).optional(), - is_home_page: z.boolean().optional(), - published_at: createOperatorMap().optional(), - archived_at: createOperatorMap().optional(), - created_at: createOperatorMap().optional(), - updated_at: createOperatorMap().optional(), - }), -) +import { createPostSchema, listAdminPostsQuerySchema } from '../validations' export const defaultAdminPostFields = [ 'id', @@ -111,9 +50,4 @@ export const adminPostRoutesMiddlewares: MiddlewareRoute[] = [ method: 'POST', middlewares: [validateAndTransformBody(createPostSchema)], }, - { - matcher: '/admin/content/posts', - method: 'PUT', - middlewares: [validateAndTransformBody(updatePostSchema)], - }, ] diff --git a/plugins/page-builder/src/api/admin/content/posts/route.ts b/plugins/page-builder/src/api/admin/content/posts/route.ts index 7e7309f5..b94ef5cf 100644 --- a/plugins/page-builder/src/api/admin/content/posts/route.ts +++ b/plugins/page-builder/src/api/admin/content/posts/route.ts @@ -3,8 +3,7 @@ import { MedusaResponse, } from '@medusajs/framework/http' import { createPostWorkflow } from '../../../../workflows/create-post' -import { updatePostWorkflow } from '../../../../workflows/update-post' -import { CreatePostDTO, UpdatePostDTO } from './middlewares' +import { CreatePostDTO } from '../validations' export const GET = async ( req: AuthenticatedMedusaRequest, @@ -40,16 +39,3 @@ export const POST = async ( res.status(200).json({ post: result }) } - -export const PUT = async ( - req: AuthenticatedMedusaRequest, - res: MedusaResponse, -) => { - const { result } = await updatePostWorkflow(req.scope).run({ - input: { - post: req.validatedBody, - }, - }) - - res.status(200).json({ post: result }) -} diff --git a/plugins/page-builder/src/api/admin/content/validations.ts b/plugins/page-builder/src/api/admin/content/validations.ts new file mode 100644 index 00000000..01807366 --- /dev/null +++ b/plugins/page-builder/src/api/admin/content/validations.ts @@ -0,0 +1,71 @@ +import { z } from 'zod' +import { + createFindParams, + createOperatorMap, +} from '@medusajs/medusa/api/utils/validators' + +import { + postContentModes, + postStatuses, + postTypes, +} from '../../../modules/page-builder/types' + +const postStatusesEnum = z.enum([...postStatuses]) +const postTypesEnum = z.enum([...postTypes]) +const postContentModesEnum = z.enum([...postContentModes]) + +export const createPostSchema = z.object({ + title: z.string(), + handle: z.string().optional(), + excerpt: z.string().optional(), + content: z.record(z.string(), z.any()).optional(), + status: postStatusesEnum.optional(), + type: postTypesEnum.optional(), + content_mode: postContentModesEnum.optional(), + seo: z.record(z.string(), z.any()).optional(), + is_home_page: z.boolean().optional(), +}) + +export const updatePostSchema = z.object({ + id: z.string(), + title: z.string().optional(), + handle: z.string().optional(), + excerpt: z.string().optional(), + content: z.record(z.string(), z.any()).optional(), + status: postStatusesEnum.optional(), + type: postTypesEnum.optional(), + content_mode: postContentModesEnum.optional(), + seo: z.record(z.string(), z.any()).optional(), + is_home_page: z.boolean().optional(), +}) + +export const deletePostSchema = z.object({ + id: z.string(), +}) + +export const listAdminPostsQuerySchema = createFindParams({ + offset: 0, + limit: 50, +}).merge( + z.object({ + q: z.string().optional(), + id: z.union([z.string(), z.array(z.string())]).optional(), + title: z.string().optional(), + handle: z.string().optional(), + status: z.union([postStatusesEnum, z.array(postStatusesEnum)]).optional(), + type: z.union([postTypesEnum, z.array(postTypesEnum)]).optional(), + content_mode: z + .union([postContentModesEnum, z.array(postContentModesEnum)]) + .optional(), + is_home_page: z.boolean().optional(), + published_at: createOperatorMap().optional(), + archived_at: createOperatorMap().optional(), + created_at: createOperatorMap().optional(), + updated_at: createOperatorMap().optional(), + }), +) + +export type CreatePostDTO = z.infer +export type UpdatePostDTO = z.infer +export type DeletePostDTO = z.infer +export type ListAdminPostsQueryDTO = z.infer diff --git a/plugins/page-builder/src/api/middlewares.ts b/plugins/page-builder/src/api/middlewares.ts index 5912884b..8d7f46b1 100644 --- a/plugins/page-builder/src/api/middlewares.ts +++ b/plugins/page-builder/src/api/middlewares.ts @@ -1,11 +1,8 @@ -import { defineMiddlewares } from '@medusajs/medusa' +import { defineMiddlewares } from '@medusajs/framework' import { adminPostRoutesMiddlewares } from './admin/content/posts/middlewares' +import { adminPostItemRoutesMiddlewares } from './admin/content/posts/[id]/middlewares' -export default defineMiddlewares({ - routes: [ - // Admin - ...adminPostRoutesMiddlewares, - - // Store - ], -}) +export default defineMiddlewares([ + ...adminPostRoutesMiddlewares, + ...adminPostItemRoutesMiddlewares, +]) diff --git a/plugins/page-builder/src/modules/page-builder/index.ts b/plugins/page-builder/src/modules/page-builder/index.ts index dd1ef37a..42f96ad0 100644 --- a/plugins/page-builder/src/modules/page-builder/index.ts +++ b/plugins/page-builder/src/modules/page-builder/index.ts @@ -7,6 +7,7 @@ export const PAGE_BUILDER_MODULE = 'page-builder' export const pageBuilderModuleEvents = Object.freeze({ POST_CREATED: 'post.created', POST_UPDATED: 'post.updated', + POST_DELETED: 'post.deleted', }) export default Module(PAGE_BUILDER_MODULE, { diff --git a/plugins/page-builder/src/modules/page-builder/types/mutations.ts b/plugins/page-builder/src/modules/page-builder/types/mutations.ts index 2bd177c8..13a1d2fd 100644 --- a/plugins/page-builder/src/modules/page-builder/types/mutations.ts +++ b/plugins/page-builder/src/modules/page-builder/types/mutations.ts @@ -21,8 +21,13 @@ export type CreatePostStepInput = Partial & { export type UpdatePostStepInput = { id: string + sections?: string[] } & Partial +export type DeletePostStepInput = { + id: string +} + export type CreatePostWorkflowInput = { post: CreatePostStepInput } @@ -30,3 +35,7 @@ export type CreatePostWorkflowInput = { export type UpdatePostWorkflowInput = { post: UpdatePostStepInput } + +export type DeletePostWorkflowInput = { + id: string +} diff --git a/plugins/page-builder/src/workflows/delete-post.ts b/plugins/page-builder/src/workflows/delete-post.ts new file mode 100644 index 00000000..7f94d887 --- /dev/null +++ b/plugins/page-builder/src/workflows/delete-post.ts @@ -0,0 +1,26 @@ +import { transform } from '@medusajs/framework/workflows-sdk' +import { emitEventStep } from '@medusajs/medusa/core-flows' +import { WorkflowResponse, createWorkflow } from '@medusajs/workflows-sdk' + +import { pageBuilderModuleEvents } from '../modules/page-builder' +import { DeletePostWorkflowInput } from '../modules/page-builder/types' +import { deletePostStep } from './steps/delete-post' + +// Delete post workflow +export const deletePostWorkflow = createWorkflow( + 'delete-post-workflow', + (input: DeletePostWorkflowInput) => { + const result = deletePostStep({ id: input.id }) + + const emitData = transform({ result }, ({ result }) => { + return { + eventName: pageBuilderModuleEvents.POST_DELETED, + data: { id: result.id }, + } + }) + + emitEventStep(emitData) + + return new WorkflowResponse(result) + }, +) diff --git a/plugins/page-builder/src/workflows/steps/delete-post.ts b/plugins/page-builder/src/workflows/steps/delete-post.ts new file mode 100644 index 00000000..4c14db69 --- /dev/null +++ b/plugins/page-builder/src/workflows/steps/delete-post.ts @@ -0,0 +1,51 @@ +import { StepResponse, createStep } from '@medusajs/workflows-sdk' +import { PAGE_BUILDER_MODULE } from '../../modules/page-builder' +import type PageBuilderService from '../../modules/page-builder/service' +import type { + CreatePostStepInput, + DeletePostStepInput, +} from '../../modules/page-builder/types' + +export const deletePostStepId = 'delete-post-step' + +export const deletePostStep = createStep( + deletePostStepId, + async (data: DeletePostStepInput, { container }) => { + const pageBuilderService = + container.resolve(PAGE_BUILDER_MODULE) + + // Get the existing post before deleting for rollback + const existingPost = await pageBuilderService.retrievePost(data.id, { + relations: ['root', 'featured_image', 'authors', 'sections', 'tags'], + }) + + await pageBuilderService.deletePosts(data.id) + + return new StepResponse({ id: data.id }, existingPost) + }, + async (existingPost, { container }) => { + if (!existingPost) return + + const pageBuilderService = + container.resolve(PAGE_BUILDER_MODULE) + + // Restore the deleted post + const createPostInput: { + id: string + sections?: string[] + } & CreatePostStepInput = { + ...existingPost, + + // relations + root_id: existingPost.root?.root?.id ?? undefined, + featured_image_id: existingPost.featured_image?.id, + authors: existingPost.authors?.map((author) => author.id), + sections: existingPost.sections?.map((section) => section.id), + tags: existingPost.tags?.map((tag) => tag.id), + } + + const restoredPost = await pageBuilderService.createPosts(createPostInput) + + return restoredPost + }, +) diff --git a/plugins/page-builder/src/workflows/steps/update-post.ts b/plugins/page-builder/src/workflows/steps/update-post.ts index b3cb21d0..f8a2269e 100644 --- a/plugins/page-builder/src/workflows/steps/update-post.ts +++ b/plugins/page-builder/src/workflows/steps/update-post.ts @@ -20,12 +20,14 @@ export const updatePostStep = createStep( return new StepResponse(post, { ...existingPost, - featured_image: existingPost.featured_image?.id, - authors: existingPost.authors.map((author) => author.id), - sections: existingPost.sections.map((section) => section.id), - tags: existingPost.tags.map((tag) => tag.id), - root: existingPost.root?.id, - }) + + // relations + root_id: existingPost.root?.root?.id ?? undefined, + featured_image_id: existingPost.featured_image?.id, + authors: existingPost.authors?.map((author) => author.id), + sections: existingPost.sections?.map((section) => section.id), + tags: existingPost.tags?.map((tag) => tag.id), + } as UpdatePostStepInput) }, async (existingData, { container }) => { if (!existingData) return From d2c8d8eae012b8fa34db99da537b19c053149889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Mon, 17 Mar 2025 09:24:54 -0600 Subject: [PATCH 15/28] feat(page-builder): add update and delete post functionality - Introduce updatePost method for modifying existing posts. - Implement deletePost method for removing posts by ID. - Update type definitions to include AdminPageBuilderUpdatePostBody and AdminPageBuilderDeletePostResponse. - Refactor types to enhance clarity and maintainability. --- .../src/sdk/admin/admin-page-builder.ts | 22 ++++++++++++++++++ plugins/page-builder/src/sdk/types.ts | 23 +++++++++++++------ 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/plugins/page-builder/src/sdk/admin/admin-page-builder.ts b/plugins/page-builder/src/sdk/admin/admin-page-builder.ts index 52553faf..bd1a0c39 100644 --- a/plugins/page-builder/src/sdk/admin/admin-page-builder.ts +++ b/plugins/page-builder/src/sdk/admin/admin-page-builder.ts @@ -4,6 +4,9 @@ import type { AdminPageBuilderCreatePostResponse, AdminPageBuilderListPostsQuery, AdminPageBuilderListPostsResponse, + AdminPageBuilderDeletePostResponse, + AdminPageBuilderUpdatePostBody, + AdminPageBuilderUpdatePostResponse, } from '../types' export class AdminPageBuilderResource { @@ -28,4 +31,23 @@ export class AdminPageBuilderResource { }, ) } + + async updatePost(id: string, data: AdminPageBuilderUpdatePostBody) { + return this.client.fetch( + `/admin/content/posts/${id}`, + { + method: 'PUT', + body: data, + }, + ) + } + + async deletePost(id: string) { + return this.client.fetch( + `/admin/content/posts/${id}`, + { + method: 'DELETE', + }, + ) + } } diff --git a/plugins/page-builder/src/sdk/types.ts b/plugins/page-builder/src/sdk/types.ts index 5232cf60..2c996401 100644 --- a/plugins/page-builder/src/sdk/types.ts +++ b/plugins/page-builder/src/sdk/types.ts @@ -1,10 +1,9 @@ -import { z } from 'zod' - import { Post } from '../modules/page-builder/types' import { CreatePostDTO, - listAdminPostsQuerySchema, -} from '../api/admin/content/posts/middlewares' + ListAdminPostsQueryDTO, + UpdatePostDTO, +} from '../api/admin/content/validations' interface PaginatedResponse { count: number @@ -12,9 +11,7 @@ interface PaginatedResponse { limit: number } -export type AdminPageBuilderListPostsQuery = z.infer< - typeof listAdminPostsQuerySchema -> +export type AdminPageBuilderListPostsQuery = ListAdminPostsQueryDTO export interface AdminPageBuilderListPostsResponse extends PaginatedResponse { posts: Post[] @@ -25,3 +22,15 @@ export type AdminPageBuilderCreatePostBody = CreatePostDTO export type AdminPageBuilderCreatePostResponse = { post: Post } + +export type AdminPageBuilderUpdatePostBody = UpdatePostDTO + +export type AdminPageBuilderUpdatePostResponse = { + post: Post +} + +export type AdminPageBuilderDeletePostResponse = { + id: string + object: string + deleted: boolean +} From fea918ae2b550437cffb68917a0f6aec7e8a8380 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Mon, 17 Mar 2025 09:25:08 -0600 Subject: [PATCH 16/28] feat(page-builder): add post update and delete hooks - Implement useAdminUpdatePost and useAdminDeletePost hooks for managing post updates and deletions. - Update PostsDataTable to utilize the new delete functionality with toast notifications. - Refactor usePostsDataTableColumns to support updated action handlers for editing, duplicating, and deleting posts. - Remove obsolete use-posts-data-table-columns file for cleaner codebase. --- .../src/admin/hooks/posts-mutations.ts | 33 +++++ .../src/admin/layouts/single-column.tsx | 11 +- .../components/posts-data-table/index.tsx | 21 +-- .../use-post-data-table-columns.tsx | 121 ++++++++++++++++++ .../use-posts-data-table-columns.tsx | 112 ---------------- 5 files changed, 175 insertions(+), 123 deletions(-) create mode 100644 plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx delete mode 100644 plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx diff --git a/plugins/page-builder/src/admin/hooks/posts-mutations.ts b/plugins/page-builder/src/admin/hooks/posts-mutations.ts index 5789726c..d959a4b5 100644 --- a/plugins/page-builder/src/admin/hooks/posts-mutations.ts +++ b/plugins/page-builder/src/admin/hooks/posts-mutations.ts @@ -3,6 +3,9 @@ import { sdk } from '../sdk' import { AdminPageBuilderCreatePostBody, AdminPageBuilderCreatePostResponse, + AdminPageBuilderDeletePostResponse, + AdminPageBuilderUpdatePostBody, + AdminPageBuilderUpdatePostResponse, } from '../../sdk/types' const QUERY_KEY = ['posts'] @@ -23,3 +26,33 @@ export const useAdminCreatePost = () => { }, }) } + +export const useAdminUpdatePost = () => { + const queryClient = useQueryClient() + return useMutation< + AdminPageBuilderUpdatePostResponse, + Error, + AdminPageBuilderUpdatePostBody + >({ + mutationFn: async (data) => { + return sdk.admin.pageBuilder.updatePost(data.id, data) + }, + mutationKey: QUERY_KEY, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: QUERY_KEY }) + }, + }) +} + +export const useAdminDeletePost = () => { + const queryClient = useQueryClient() + return useMutation({ + mutationFn: async (id: string) => { + return sdk.admin.pageBuilder.deletePost(id) + }, + mutationKey: QUERY_KEY, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: QUERY_KEY }) + }, + }) +} diff --git a/plugins/page-builder/src/admin/layouts/single-column.tsx b/plugins/page-builder/src/admin/layouts/single-column.tsx index 73fb5f44..539ac146 100644 --- a/plugins/page-builder/src/admin/layouts/single-column.tsx +++ b/plugins/page-builder/src/admin/layouts/single-column.tsx @@ -1,11 +1,16 @@ +import { Toaster } from "@medusajs/ui" + export type SingleColumnLayoutProps = { children: React.ReactNode } export const SingleColumnLayout = ({ children }: SingleColumnLayoutProps) => { return ( -
- {children} -
+ <> + +
+ {children} +
+ ) } \ No newline at end of file diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx index 19105895..6c730c44 100644 --- a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx @@ -4,14 +4,15 @@ import { DataTableFilteringState, DataTablePaginationState, DataTableSortingState, + toast, useDataTable, } from '@medusajs/ui' import { useMemo, useState } from 'react' import { useNavigate } from 'react-router-dom' -import { usePostsDataTableColumns } from './use-posts-data-table-columns' +import { usePostsDataTableColumns } from './use-post-data-table-columns' import { useAdminListPosts } from '../../../../hooks/posts-queries' import { Post, PostStatus, PostType } from '../../../../../modules/page-builder/types' - +import { useAdminDeletePost } from '../../../../hooks/posts-mutations' // Create filter helper const filterHelper = createDataTableFilterHelper() @@ -49,6 +50,7 @@ const filters = [ export const PostsDataTable = () => { const navigate = useNavigate() + const { mutateAsync: deletePost, isPending: isDeleting } = useAdminDeletePost() const limit = 10 const [pagination, setPagination] = useState({ pageSize: limit, @@ -70,19 +72,22 @@ export const PostsDataTable = () => { return (filtering.type || []) as PostType[] }, [filtering]) - const handleEdit = (post: Post) => { + const handleEdit = (id: string) => { // navigate(`/editor/${post.type}/${post.id}`) navigate(`editor/test`) // TODO: change to the actual content detail page } - const handleDuplicate = (post: Post) => { - console.log('duplicate post', post.id) + const handleDuplicate = (id: string) => { + console.log('duplicate post', id) + + toast.success('Page duplicated') // Implement duplication logic here } - const handleDelete = (post: Post) => { - console.log('delete post', post.id) - // Implement deletion logic here + const handleDelete = async (id: string) => { + await deletePost(id) + + toast.success('Page deleted') } const columns = usePostsDataTableColumns({ diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx new file mode 100644 index 00000000..488b78f1 --- /dev/null +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx @@ -0,0 +1,121 @@ +import React from 'react' +import { createDataTableColumnHelper, Text, StatusBadge, usePrompt } from '@medusajs/ui' +import { PencilSquare, SquareTwoStackMini, Trash } from '@medusajs/icons' +import { Post } from '../../../../../modules/page-builder/types' + +export type ColumnActions = { + onEdit?: (id: string) => void + onDuplicate?: (id: string) => void + onDelete?: (id: string) => void +} + +const columnHelper = createDataTableColumnHelper() + +/** + * Hook that returns column definitions for the PostsDataTable + */ +export const usePostsDataTableColumns = (actions: ColumnActions = {}) => { + const { onEdit, onDuplicate, onDelete } = actions + const prompt = usePrompt() + + return React.useMemo( + () => [ + columnHelper.accessor('title', { + header: 'Title', + enableSorting: true, + sortLabel: 'Title', + }), + columnHelper.accessor('handle', { + header: 'Handle', + enableSorting: true, + }), + columnHelper.accessor('status', { + header: 'Status', + cell: ({ getValue }) => { + const status = getValue() + return ( + + {status === 'published' ? 'Published' : 'Draft'} + + ) + }, + enableSorting: true, + }), + columnHelper.accessor('type', { + header: 'Type', + enableSorting: true, + }), + columnHelper.accessor('created_at', { + header: 'Date Created', + cell: ({ getValue }) => { + const date = new Date(getValue()) + return {date.toLocaleDateString()} + }, + enableSorting: true, + }), + columnHelper.accessor('updated_at', { + header: 'Last Updated', + cell: ({ getValue }) => { + const date = new Date(getValue()) + return {date.toLocaleDateString()} + }, + enableSorting: true, + }), + columnHelper.action({ + // @ts-ignore + actions: ({ row }) => [ + [ + { + icon: , + label: 'Edit', + onClick: () => { + if (onEdit) { + onEdit(row.original.id) + } else { + console.log('edit', row.original.id) + } + }, + }, + ], + [ + { + icon: , + label: 'Duplicate', + onClick: () => { + if (onDuplicate) { + onDuplicate(row.original.id) + } else { + console.log('duplicate', row.original.id) + } + }, + }, + ], + [ + { + icon: (), + label: 'Delete', + onClick: async () => { + const res = await prompt({ + title: 'Are you sure?', + description: `You are about to delete the page "${row.original.title}". This action cannot be undone.`, + confirmText: 'Delete', + cancelText: 'Cancel', + }) + + if (!res) { + return + } + + onDelete?.(row.original.id) + }, + }, + ], + ], + }), + ], + [onEdit, onDuplicate, onDelete], + ) +} diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx deleted file mode 100644 index 45d4ecab..00000000 --- a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-posts-data-table-columns.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import React from "react" -import { - createDataTableColumnHelper, - Text, - StatusBadge -} from "@medusajs/ui" -import { PencilSquare, SquareTwoStackMini, Trash } from "@medusajs/icons" -import { Post } from "../../../../../modules/page-builder/types" - - -export type ColumnActions = { - onEdit?: (post: Post) => void - onDuplicate?: (post: Post) => void - onDelete?: (post: Post) => void -} - -const columnHelper = createDataTableColumnHelper() - -/** - * Hook that returns column definitions for the PostsDataTable - */ -export const usePostsDataTableColumns = (actions: ColumnActions = {}) => { - const { onEdit, onDuplicate, onDelete } = actions - - return React.useMemo(() => [ - columnHelper.accessor("title", { - header: "Title", - enableSorting: true, - sortLabel: "Title", - }), - columnHelper.accessor("handle", { - header: "Handle", - enableSorting: true, - }), - columnHelper.accessor("status", { - header: "Status", - cell: ({ getValue }) => { - const status = getValue() - return ( - - {status === "published" ? "Published" : "Draft"} - - ) - }, - enableSorting: true, - }), - columnHelper.accessor("type", { - header: "Type", - enableSorting: true, - }), - columnHelper.accessor("created_at", { - header: "Date Created", - cell: ({ getValue }) => { - const date = new Date(getValue()) - return {date.toLocaleDateString()} - }, - enableSorting: true, - }), - columnHelper.accessor("updated_at", { - header: "Last Updated", - cell: ({ getValue }) => { - const date = new Date(getValue()) - return {date.toLocaleDateString()} - }, - enableSorting: true, - }), - columnHelper.action({ - // @ts-ignore - actions: ({ row }) => [ - [ - { - icon: , - label: 'Edit', - onClick: () => { - if (onEdit) { - onEdit(row.original) - } else { - console.log('edit', row.original.id) - } - }, - }, - ], - [ - { - icon: , - label: 'Duplicate', - onClick: () => { - if (onDuplicate) { - onDuplicate(row.original) - } else { - console.log('duplicate', row.original.id) - } - }, - }, - ], - [ - { - icon: , - label: 'Delete', - onClick: () => { - if (onDelete) { - onDelete(row.original) - } else { - console.log('delete', row.original.id) - } - }, - }, - ], - ], - }), - ], [onEdit, onDuplicate, onDelete]) -} From 36c858225a14b19ce3a2aebbfcc42eba23b62a88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Wed, 19 Mar 2025 06:50:51 -0600 Subject: [PATCH 17/28] feat(page-builder): implement duplicate post workflow and related steps - Add duplicatePostWorkflow to handle the duplication of posts. - Create duplicatePostStep for generating a new post based on an existing one. - Implement duplicatePostRelationsStep to manage the relations of the duplicated post. - Ensure proper handling of sections, featured images, authors, and tags during duplication. --- .../src/workflows/duplicate-post.ts | 31 +++++++ .../steps/duplicate-post-relations.ts | 83 +++++++++++++++++++ .../src/workflows/steps/duplicate-post.ts | 50 +++++++++++ 3 files changed, 164 insertions(+) create mode 100644 plugins/page-builder/src/workflows/duplicate-post.ts create mode 100644 plugins/page-builder/src/workflows/steps/duplicate-post-relations.ts create mode 100644 plugins/page-builder/src/workflows/steps/duplicate-post.ts diff --git a/plugins/page-builder/src/workflows/duplicate-post.ts b/plugins/page-builder/src/workflows/duplicate-post.ts new file mode 100644 index 00000000..7dc54f24 --- /dev/null +++ b/plugins/page-builder/src/workflows/duplicate-post.ts @@ -0,0 +1,31 @@ +import { transform } from '@medusajs/framework/workflows-sdk' +import { emitEventStep } from '@medusajs/medusa/core-flows' +import { WorkflowResponse, createWorkflow } from '@medusajs/workflows-sdk' +import { pageBuilderModuleEvents } from '../modules/page-builder' +import type { DuplicatePostWorkflowInput } from '../modules/page-builder/types' +import { duplicatePostStep } from './steps/duplicate-post' +import { duplicatePostRelationsStep } from './steps/duplicate-post-relations' + +// Duplicate post workflow +export const duplicatePostWorkflow = createWorkflow( + 'duplicate-post-workflow', + (input: DuplicatePostWorkflowInput) => { + const newPost = duplicatePostStep({ id: input.id }) + + const postWithRelations = duplicatePostRelationsStep({ + originalId: input.id, + newId: newPost.id, + }) + + const emitData = transform({ post: newPost }, ({ post }) => { + return { + eventName: pageBuilderModuleEvents.POST_CREATED, + data: { id: post.id }, + } + }) + + emitEventStep(emitData) + + return new WorkflowResponse(postWithRelations) + }, +) diff --git a/plugins/page-builder/src/workflows/steps/duplicate-post-relations.ts b/plugins/page-builder/src/workflows/steps/duplicate-post-relations.ts new file mode 100644 index 00000000..1d2ed104 --- /dev/null +++ b/plugins/page-builder/src/workflows/steps/duplicate-post-relations.ts @@ -0,0 +1,83 @@ +import { StepResponse, createStep } from '@medusajs/workflows-sdk' +import { PAGE_BUILDER_MODULE } from '../../modules/page-builder' +import type PageBuilderService from '../../modules/page-builder/service' +import { PostSection } from 'src/modules/page-builder/types' + +export const duplicatePostRelationsStepId = 'duplicate-post-relations-step' + +type DuplicatePostRelationsStepInput = { + originalId: string + newId: string +} + +export const duplicatePostRelationsStep = createStep( + duplicatePostRelationsStepId, + async (data: DuplicatePostRelationsStepInput, { container }) => { + const pageBuilderService = + container.resolve(PAGE_BUILDER_MODULE) + + // Get the original post with all its relations + const originalPost = await pageBuilderService.retrievePost( + data.originalId, + { + relations: ['sections', 'featured_image', 'authors', 'tags'], + }, + ) + + const newPost = await pageBuilderService.retrievePost(data.newId) + const newPostSectionsIds: string[] = [] + + // Duplicate the sections since these should be unique to the post + if (originalPost.sections?.length > 0) { + type SectionInput = Parameters< + typeof pageBuilderService.createPostSections + >['0'][number] + + const sectionsToCreate: SectionInput[] = originalPost.sections.map( + (section) => ({ + ...section, + id: undefined, + post_template: undefined, + post_template_id: undefined, + + // Set the new post relation + post: newPost.id, + post_id: newPost.id, + }), + ) + + const newPostSections = + await pageBuilderService.createPostSections(sectionsToCreate) + + newPostSectionsIds.push(...newPostSections.map(({ id }) => id)) + } + + const relationsToUpdate = { + sections: newPostSectionsIds, + featured_image: originalPost.featured_image?.id, + authors: originalPost.authors?.map((author) => author.id) ?? [], + tags: originalPost.tags?.map((tag) => tag.id) ?? [], + } + + const updatedPost = await pageBuilderService.updatePosts({ + id: newPost.id, + ...relationsToUpdate, + }) + + return new StepResponse(updatedPost, { + relationsUpdated: relationsToUpdate, + }) + }, + async (data, { container }) => { + if (!data?.relationsUpdated) return + + const pageBuilderService = + container.resolve(PAGE_BUILDER_MODULE) + + const { sections, featured_image, authors, tags } = data.relationsUpdated + + if (sections?.length) { + await pageBuilderService.deletePostSections(sections) + } + }, +) diff --git a/plugins/page-builder/src/workflows/steps/duplicate-post.ts b/plugins/page-builder/src/workflows/steps/duplicate-post.ts new file mode 100644 index 00000000..1da9f3e9 --- /dev/null +++ b/plugins/page-builder/src/workflows/steps/duplicate-post.ts @@ -0,0 +1,50 @@ +import { StepResponse, createStep } from '@medusajs/workflows-sdk' +import { PAGE_BUILDER_MODULE } from '../../modules/page-builder' +import type PageBuilderService from '../../modules/page-builder/service' +import type { DuplicatePostStepInput } from '../../modules/page-builder/types' + +export const duplicatePostStepId = 'duplicate-post-step' + +export const duplicatePostStep = createStep( + duplicatePostStepId, + async (data: DuplicatePostStepInput, { container }) => { + const pageBuilderService = + container.resolve(PAGE_BUILDER_MODULE) + + // Get the existing post to duplicate + const existingPost = await pageBuilderService.retrievePost(data.id) + + // Create a new title with "(copy)" suffix + const newTitle = `${existingPost.title || 'Untitled'} (copy)` + + // Create a new handle or make it null to generate a new one + const handle = existingPost.handle ? `${existingPost.handle}-copy` : null + + // Create a new post with the copied data + const newPost = await pageBuilderService.createPosts({ + title: newTitle, + handle, + excerpt: existingPost.excerpt, + content: existingPost.content, + status: 'draft', // Always start as draft + type: existingPost.type, + content_mode: existingPost.content_mode, + seo: existingPost.seo ? { ...existingPost.seo } : undefined, + is_home_page: false, // Never copy home page status + }) + + return new StepResponse(newPost, { + originalId: existingPost.id, + newId: newPost.id, + }) + }, + async (data, { container }) => { + if (!data) return + + const pageBuilderService = + container.resolve(PAGE_BUILDER_MODULE) + + // Delete the created post if workflow fails + await pageBuilderService.deletePosts(data.newId) + }, +) From daadc421e743c46168aa0296ff176f59b62dfb8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Wed, 19 Mar 2025 06:52:07 -0600 Subject: [PATCH 18/28] feat(page-builder): add duplicate post functionality and related types - Introduce DuplicatePostStepInput and DuplicatePostWorkflowInput types for handling post duplication. - Implement AdminPageBuilderDuplicatePostResponse type for response structure. - Add duplicatePost method in AdminPageBuilderResource to facilitate post duplication via API. --- .../src/modules/page-builder/types/mutations.ts | 8 ++++++++ .../src/sdk/admin/admin-page-builder.ts | 14 ++++++++++++-- plugins/page-builder/src/sdk/types.ts | 8 ++++++-- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/plugins/page-builder/src/modules/page-builder/types/mutations.ts b/plugins/page-builder/src/modules/page-builder/types/mutations.ts index 13a1d2fd..5cae9d14 100644 --- a/plugins/page-builder/src/modules/page-builder/types/mutations.ts +++ b/plugins/page-builder/src/modules/page-builder/types/mutations.ts @@ -39,3 +39,11 @@ export type UpdatePostWorkflowInput = { export type DeletePostWorkflowInput = { id: string } + +export type DuplicatePostStepInput = { + id: string +} + +export type DuplicatePostWorkflowInput = { + id: string +} diff --git a/plugins/page-builder/src/sdk/admin/admin-page-builder.ts b/plugins/page-builder/src/sdk/admin/admin-page-builder.ts index bd1a0c39..7f28974e 100644 --- a/plugins/page-builder/src/sdk/admin/admin-page-builder.ts +++ b/plugins/page-builder/src/sdk/admin/admin-page-builder.ts @@ -7,6 +7,7 @@ import type { AdminPageBuilderDeletePostResponse, AdminPageBuilderUpdatePostBody, AdminPageBuilderUpdatePostResponse, + AdminPageBuilderDuplicatePostResponse, } from '../types' export class AdminPageBuilderResource { @@ -14,7 +15,7 @@ export class AdminPageBuilderResource { async listPosts(query: AdminPageBuilderListPostsQuery) { return this.client.fetch( - `/admin/content/posts`, + '/admin/content/posts', { method: 'GET', query, @@ -24,7 +25,7 @@ export class AdminPageBuilderResource { async createPost(data: AdminPageBuilderCreatePostBody) { return this.client.fetch( - `/admin/content/posts`, + '/admin/content/posts', { method: 'POST', body: data, @@ -50,4 +51,13 @@ export class AdminPageBuilderResource { }, ) } + + async duplicatePost(id: string) { + return this.client.fetch( + `/admin/content/posts/${id}/duplicate`, + { + method: 'POST', + }, + ) + } } diff --git a/plugins/page-builder/src/sdk/types.ts b/plugins/page-builder/src/sdk/types.ts index 2c996401..27797d5c 100644 --- a/plugins/page-builder/src/sdk/types.ts +++ b/plugins/page-builder/src/sdk/types.ts @@ -1,5 +1,5 @@ -import { Post } from '../modules/page-builder/types' -import { +import type { Post } from '../modules/page-builder/types' +import type { CreatePostDTO, ListAdminPostsQueryDTO, UpdatePostDTO, @@ -34,3 +34,7 @@ export type AdminPageBuilderDeletePostResponse = { object: string deleted: boolean } + +export type AdminPageBuilderDuplicatePostResponse = { + post: Post +} From 087769a0136385b0afa62913e592f35bc59f94eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Wed, 19 Mar 2025 06:52:29 -0600 Subject: [PATCH 19/28] feat(page-builder): add POST route for duplicating posts - Implement POST route handler in route.ts to facilitate post duplication. - Utilize duplicatePostWorkflow to process duplication requests and return the duplicated post. --- .../content/posts/[id]/duplicate/route.ts | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 plugins/page-builder/src/api/admin/content/posts/[id]/duplicate/route.ts diff --git a/plugins/page-builder/src/api/admin/content/posts/[id]/duplicate/route.ts b/plugins/page-builder/src/api/admin/content/posts/[id]/duplicate/route.ts new file mode 100644 index 00000000..bac143df --- /dev/null +++ b/plugins/page-builder/src/api/admin/content/posts/[id]/duplicate/route.ts @@ -0,0 +1,20 @@ +import type { + AuthenticatedMedusaRequest, + MedusaResponse, +} from '@medusajs/framework/http' +import { duplicatePostWorkflow } from '../../../../../../workflows/duplicate-post' + +export const POST = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse, +) => { + const id = req.params.id + + const { result } = await duplicatePostWorkflow(req.scope).run({ + input: { + id, + }, + }) + + res.status(200).json({ post: result }) +} From 3925212dd5188c157143a5e854b95569d34c3dad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Wed, 19 Mar 2025 06:53:53 -0600 Subject: [PATCH 20/28] feat(page-builder): add duplicate post functionality to posts data table - Implement useAdminDuplicatePost hook for duplicating posts. - Update PostsDataTable to include duplication action with toast notifications. - Refactor usePostsDataTableColumns to support duplicate action in column definitions. --- .../src/admin/hooks/posts-mutations.ts | 16 +- .../components/posts-data-table/index.tsx | 268 +++++++++--------- .../use-post-data-table-columns.tsx | 221 +++++++-------- 3 files changed, 263 insertions(+), 242 deletions(-) diff --git a/plugins/page-builder/src/admin/hooks/posts-mutations.ts b/plugins/page-builder/src/admin/hooks/posts-mutations.ts index d959a4b5..201ae042 100644 --- a/plugins/page-builder/src/admin/hooks/posts-mutations.ts +++ b/plugins/page-builder/src/admin/hooks/posts-mutations.ts @@ -1,9 +1,10 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' import { sdk } from '../sdk' -import { +import type { AdminPageBuilderCreatePostBody, AdminPageBuilderCreatePostResponse, AdminPageBuilderDeletePostResponse, + AdminPageBuilderDuplicatePostResponse, AdminPageBuilderUpdatePostBody, AdminPageBuilderUpdatePostResponse, } from '../../sdk/types' @@ -56,3 +57,16 @@ export const useAdminDeletePost = () => { }, }) } + +export const useAdminDuplicatePost = () => { + const queryClient = useQueryClient() + return useMutation({ + mutationFn: async (id: string) => { + return sdk.admin.pageBuilder.duplicatePost(id) + }, + mutationKey: QUERY_KEY, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: QUERY_KEY }) + }, + }) +} diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx index 6c730c44..61c0155d 100644 --- a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx @@ -1,148 +1,156 @@ import { - createDataTableFilterHelper, - DataTable, - DataTableFilteringState, - DataTablePaginationState, - DataTableSortingState, - toast, - useDataTable, -} from '@medusajs/ui' -import { useMemo, useState } from 'react' - import { useNavigate } from 'react-router-dom' -import { usePostsDataTableColumns } from './use-post-data-table-columns' -import { useAdminListPosts } from '../../../../hooks/posts-queries' -import { Post, PostStatus, PostType } from '../../../../../modules/page-builder/types' -import { useAdminDeletePost } from '../../../../hooks/posts-mutations' + type DataTableFilteringState, + type DataTablePaginationState, + type DataTableSortingState, + createDataTableFilterHelper, + DataTable, + toast, + useDataTable, +} from "@medusajs/ui"; +import { useMemo, useState } from "react"; +import { useNavigate } from "react-router-dom"; +import { usePostsDataTableColumns } from "./use-post-data-table-columns"; +import { useAdminListPosts } from "../../../../hooks/posts-queries"; +import type { + Post, + PostStatus, + PostType, +} from "../../../../../modules/page-builder/types"; +import { + useAdminDeletePost, + useAdminDuplicatePost, +} from "../../../../hooks/posts-mutations"; + // Create filter helper -const filterHelper = createDataTableFilterHelper() +const filterHelper = createDataTableFilterHelper(); // Define filters const filters = [ - filterHelper.accessor("status", { - type: "select", - label: "Status", - options: [ - { - label: "Published", - value: "published", - }, - { - label: "Draft", - value: "draft", - }, - ], - }), - filterHelper.accessor("type", { - type: "select", - label: "Type", - options: [ - { - label: "Page", - value: "page", - }, - { - label: "Post", - value: "post", - }, - ], - }), -] + filterHelper.accessor("status", { + type: "select", + label: "Status", + options: [ + { + label: "Published", + value: "published", + }, + { + label: "Draft", + value: "draft", + }, + ], + }), + filterHelper.accessor("type", { + type: "select", + label: "Type", + options: [ + { + label: "Page", + value: "page", + }, + { + label: "Post", + value: "post", + }, + ], + }), +]; export const PostsDataTable = () => { - const navigate = useNavigate() - const { mutateAsync: deletePost, isPending: isDeleting } = useAdminDeletePost() - const limit = 10 - const [pagination, setPagination] = useState({ - pageSize: limit, - pageIndex: 0, - }) - const [search, setSearch] = useState("") - const [filtering, setFiltering] = useState({}) - const [sorting, setSorting] = useState(null) + const navigate = useNavigate(); + const { mutateAsync: deletePost } = useAdminDeletePost(); + const { mutateAsync: duplicatePost } = useAdminDuplicatePost(); + const limit = 10; + const [pagination, setPagination] = useState({ + pageSize: limit, + pageIndex: 0, + }); + const [search, setSearch] = useState(""); + const [filtering, setFiltering] = useState({}); + const [sorting, setSorting] = useState(null); + + const offset = useMemo(() => { + return pagination.pageIndex * limit; + }, [pagination]); - const offset = useMemo(() => { - return pagination.pageIndex * limit - }, [pagination]) - - const statusFilters = useMemo(() => { - return (filtering.status || []) as PostStatus[] - }, [filtering]) + const statusFilters = useMemo(() => { + return (filtering.status || []) as PostStatus[]; + }, [filtering]); - const typeFilters = useMemo(() => { - return (filtering.type || []) as PostType[] - }, [filtering]) + const typeFilters = useMemo(() => { + return (filtering.type || []) as PostType[]; + }, [filtering]); - const handleEdit = (id: string) => { - // navigate(`/editor/${post.type}/${post.id}`) - navigate(`editor/test`) // TODO: change to the actual content detail page - } + const handleEdit = (id: string) => { + // navigate(`/editor/${post.type}/${post.id}`) + navigate("editor/test"); // TODO: change to the actual content detail page + }; - const handleDuplicate = (id: string) => { - console.log('duplicate post', id) + const handleDuplicate = async (id: string) => { + await duplicatePost(id); - toast.success('Page duplicated') - // Implement duplication logic here - } + toast.success("Page duplicated"); + }; - const handleDelete = async (id: string) => { - await deletePost(id) + const handleDelete = async (id: string) => { + await deletePost(id); - toast.success('Page deleted') - } + toast.success("Page deleted"); + }; - const columns = usePostsDataTableColumns({ - onEdit: handleEdit, - onDuplicate: handleDuplicate, - onDelete: handleDelete, - }) + const columns = usePostsDataTableColumns({ + onEdit: handleEdit, + onDuplicate: handleDuplicate, + onDelete: handleDelete, + }); - const { data, isLoading } = useAdminListPosts({ - limit, - offset, - q: search, - status: statusFilters, - type: typeFilters, - order: sorting ? `${sorting.desc ? "-" : ""}${sorting.id}` : undefined, - }) + const { data, isLoading } = useAdminListPosts({ + limit, + offset, + q: search, + status: statusFilters, + type: typeFilters, + order: sorting ? `${sorting.desc ? "-" : ""}${sorting.id}` : undefined, + }); - const table = useDataTable({ - columns, - data: data?.posts || [], - getRowId: (row) => row.id, - rowCount: data?.count || 0, - isLoading, - pagination: { - state: pagination, - onPaginationChange: setPagination, - }, - search: { - state: search, - onSearchChange: setSearch, - }, - filtering: { - state: filtering, - onFilteringChange: setFiltering, - }, - filters, - sorting: { - state: sorting, - onSortingChange: setSorting, - }, - }) + const table = useDataTable({ + columns, + data: data?.posts || [], + getRowId: (row) => row.id, + rowCount: data?.count || 0, + isLoading, + pagination: { + state: pagination, + onPaginationChange: setPagination, + }, + search: { + state: search, + onSearchChange: setSearch, + }, + filtering: { + state: filtering, + onFilteringChange: setFiltering, + }, + filters, + sorting: { + state: sorting, + onSortingChange: setSorting, + }, + }); - return ( - - -
- -
- - -
-
-
- - -
- ) -} + return ( + + +
+ +
+ + +
+
+
+ + +
+ ); +}; diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx index 488b78f1..d1a7d019 100644 --- a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx @@ -1,121 +1,120 @@ -import React from 'react' -import { createDataTableColumnHelper, Text, StatusBadge, usePrompt } from '@medusajs/ui' -import { PencilSquare, SquareTwoStackMini, Trash } from '@medusajs/icons' -import { Post } from '../../../../../modules/page-builder/types' +import React from "react"; +import { + createDataTableColumnHelper, + Text, + StatusBadge, + usePrompt, +} from "@medusajs/ui"; +import { PencilSquare, SquareTwoStackMini, Trash } from "@medusajs/icons"; +import type { Post } from "../../../../../modules/page-builder/types"; export type ColumnActions = { - onEdit?: (id: string) => void - onDuplicate?: (id: string) => void - onDelete?: (id: string) => void -} + onEdit?: (id: string) => void; + onDuplicate?: (id: string) => void; + onDelete?: (id: string) => void; +}; -const columnHelper = createDataTableColumnHelper() +const columnHelper = createDataTableColumnHelper(); /** * Hook that returns column definitions for the PostsDataTable */ export const usePostsDataTableColumns = (actions: ColumnActions = {}) => { - const { onEdit, onDuplicate, onDelete } = actions - const prompt = usePrompt() + const { onEdit, onDuplicate, onDelete } = actions; + const prompt = usePrompt(); - return React.useMemo( - () => [ - columnHelper.accessor('title', { - header: 'Title', - enableSorting: true, - sortLabel: 'Title', - }), - columnHelper.accessor('handle', { - header: 'Handle', - enableSorting: true, - }), - columnHelper.accessor('status', { - header: 'Status', - cell: ({ getValue }) => { - const status = getValue() - return ( - - {status === 'published' ? 'Published' : 'Draft'} - - ) - }, - enableSorting: true, - }), - columnHelper.accessor('type', { - header: 'Type', - enableSorting: true, - }), - columnHelper.accessor('created_at', { - header: 'Date Created', - cell: ({ getValue }) => { - const date = new Date(getValue()) - return {date.toLocaleDateString()} - }, - enableSorting: true, - }), - columnHelper.accessor('updated_at', { - header: 'Last Updated', - cell: ({ getValue }) => { - const date = new Date(getValue()) - return {date.toLocaleDateString()} - }, - enableSorting: true, - }), - columnHelper.action({ - // @ts-ignore - actions: ({ row }) => [ - [ - { - icon: , - label: 'Edit', - onClick: () => { - if (onEdit) { - onEdit(row.original.id) - } else { - console.log('edit', row.original.id) - } - }, - }, - ], - [ - { - icon: , - label: 'Duplicate', - onClick: () => { - if (onDuplicate) { - onDuplicate(row.original.id) - } else { - console.log('duplicate', row.original.id) - } - }, - }, - ], - [ - { - icon: (), - label: 'Delete', - onClick: async () => { - const res = await prompt({ - title: 'Are you sure?', - description: `You are about to delete the page "${row.original.title}". This action cannot be undone.`, - confirmText: 'Delete', - cancelText: 'Cancel', - }) - - if (!res) { - return - } + return React.useMemo( + () => [ + columnHelper.accessor("title", { + header: "Title", + enableSorting: true, + sortLabel: "Title", + }), + columnHelper.accessor("handle", { + header: "Handle", + enableSorting: true, + }), + columnHelper.accessor("status", { + header: "Status", + cell: ({ getValue }) => { + const status = getValue(); + return ( + + {status === "published" ? "Published" : "Draft"} + + ); + }, + enableSorting: true, + }), + columnHelper.accessor("type", { + header: "Type", + enableSorting: true, + }), + columnHelper.accessor("created_at", { + header: "Date Created", + cell: ({ getValue }) => { + const date = new Date(getValue()); + return {date.toLocaleDateString()}; + }, + enableSorting: true, + }), + columnHelper.accessor("updated_at", { + header: "Last Updated", + cell: ({ getValue }) => { + const date = new Date(getValue()); + return {date.toLocaleDateString()}; + }, + enableSorting: true, + }), + columnHelper.action({ + // @ts-ignore + actions: ({ row }) => [ + [ + { + icon: , + label: "Edit", + onClick: () => { + if (onEdit) { + onEdit(row.original.id); + } else { + console.log("edit", row.original.id); + } + }, + }, + ], + [ + { + icon: , + label: "Duplicate", + onClick: () => { + onDuplicate?.(row.original.id); + }, + }, + ], + [ + { + icon: , + label: "Delete", + onClick: async () => { + const res = await prompt({ + title: "Are you sure?", + description: `You are about to delete the page "${row.original.title}". This action cannot be undone.`, + confirmText: "Delete", + cancelText: "Cancel", + }); - onDelete?.(row.original.id) - }, - }, - ], - ], - }), - ], - [onEdit, onDuplicate, onDelete], - ) -} + if (!res) return; + + onDelete?.(row.original.id); + }, + }, + ], + ], + }), + ], + [onEdit, onDuplicate, onDelete, prompt], + ); +}; From e8921f12d04a57b3ab4da74adc4eddbad5a762cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Wed, 19 Mar 2025 06:59:07 -0600 Subject: [PATCH 21/28] refactor(page-builder): remove unused PostSection import in duplicate post relations step --- .../page-builder/src/workflows/steps/duplicate-post-relations.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/page-builder/src/workflows/steps/duplicate-post-relations.ts b/plugins/page-builder/src/workflows/steps/duplicate-post-relations.ts index 1d2ed104..2c0989dd 100644 --- a/plugins/page-builder/src/workflows/steps/duplicate-post-relations.ts +++ b/plugins/page-builder/src/workflows/steps/duplicate-post-relations.ts @@ -1,7 +1,6 @@ import { StepResponse, createStep } from '@medusajs/workflows-sdk' import { PAGE_BUILDER_MODULE } from '../../modules/page-builder' import type PageBuilderService from '../../modules/page-builder/service' -import { PostSection } from 'src/modules/page-builder/types' export const duplicatePostRelationsStepId = 'duplicate-post-relations-step' From b6c60a1b8910aabba3ed2f5b70ddc8ef69b5c8cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Wed, 19 Mar 2025 11:35:04 -0600 Subject: [PATCH 22/28] refactor(page-builder): change imports to type imports in posts route --- plugins/page-builder/src/api/admin/content/posts/route.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/page-builder/src/api/admin/content/posts/route.ts b/plugins/page-builder/src/api/admin/content/posts/route.ts index b94ef5cf..cd0c6375 100644 --- a/plugins/page-builder/src/api/admin/content/posts/route.ts +++ b/plugins/page-builder/src/api/admin/content/posts/route.ts @@ -1,9 +1,9 @@ -import { +import type { AuthenticatedMedusaRequest, MedusaResponse, } from '@medusajs/framework/http' import { createPostWorkflow } from '../../../../workflows/create-post' -import { CreatePostDTO } from '../validations' +import type { CreatePostDTO } from '../validations' export const GET = async ( req: AuthenticatedMedusaRequest, From 3626b2af489ff4c62dec2970c137f082adde8bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Wed, 19 Mar 2025 11:35:53 -0600 Subject: [PATCH 23/28] feat(page-builder): make post fields searchable in PostModel --- .../page-builder/src/modules/page-builder/models/post.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/page-builder/src/modules/page-builder/models/post.ts b/plugins/page-builder/src/modules/page-builder/models/post.ts index 8f100e09..10adb945 100644 --- a/plugins/page-builder/src/modules/page-builder/models/post.ts +++ b/plugins/page-builder/src/modules/page-builder/models/post.ts @@ -8,9 +8,9 @@ import { postContentModes, postStatuses, postTypes } from '../types/common' export const PostModel = model.define('post', { id: model.id({ prefix: 'post' }).primaryKey(), type: model.enum([...postTypes]), - title: model.text(), - handle: model.text().unique().nullable(), - excerpt: model.text().nullable(), + title: model.text().searchable(), + handle: model.text().unique().searchable().nullable(), + excerpt: model.text().searchable().nullable(), content: model.json().nullable(), status: model.enum([...postStatuses]).default('draft'), content_mode: model.enum([...postContentModes]).default('advanced'), From 72e2490ef65af5d37c7d371b9077910829374c0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Wed, 19 Mar 2025 11:38:12 -0600 Subject: [PATCH 24/28] feat(page-builder): implement useQueryParams hook and refactor PostsDataTable - Add useQueryParams hook for managing query parameters in URL. - Refactor PostsDataTable to utilize usePostTableQuery for handling pagination, filtering, and sorting. - Simplify state management by integrating query parameters into the data table logic. --- .../src/admin/hooks/use-query-params.tsx | 50 +++++ .../components/posts-data-table/index.tsx | 47 ++-- .../posts-data-table/use-post-table-query.tsx | 211 ++++++++++++++++++ 3 files changed, 283 insertions(+), 25 deletions(-) create mode 100644 plugins/page-builder/src/admin/hooks/use-query-params.tsx create mode 100644 plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-table-query.tsx diff --git a/plugins/page-builder/src/admin/hooks/use-query-params.tsx b/plugins/page-builder/src/admin/hooks/use-query-params.tsx new file mode 100644 index 00000000..39ba4652 --- /dev/null +++ b/plugins/page-builder/src/admin/hooks/use-query-params.tsx @@ -0,0 +1,50 @@ +import { useSearchParams } from "react-router-dom"; +import { useMemo } from "react"; + +type QueryParams = { + [key in T]: string | undefined; +}; + +type SetQueryParams = ( + params: Partial>, +) => void; + +export function useQueryParams( + keys: T[], + prefix?: string, +): { queryObject: QueryParams; setQueryObject: SetQueryParams } { + const [params, setParams] = useSearchParams(); + + // Use useMemo to create the query object from URL params + const queryObject = useMemo(() => { + const result = {} as QueryParams; + + for (const key of keys) { + const prefixedKey = prefix ? `${prefix}_${key}` : key; + const value = params.get(prefixedKey) || undefined; + result[key] = value; + } + + return result; + }, [keys, params, prefix]); + + const setQueryObject = (newParams: Partial>) => { + const newSearchParams = new URLSearchParams(params); + + for (const [key, value] of Object.entries(newParams)) { + const prefixedKey = prefix ? `${prefix}_${key}` : key; + if (value === undefined || value === null) { + newSearchParams.delete(prefixedKey); + } else { + newSearchParams.set(prefixedKey, String(value)); + } + } + + setParams(newSearchParams); + }; + + return { + queryObject, + setQueryObject, + }; +} diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx index 61c0155d..3ef4057a 100644 --- a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx @@ -1,13 +1,10 @@ import { - type DataTableFilteringState, - type DataTablePaginationState, - type DataTableSortingState, createDataTableFilterHelper, DataTable, toast, useDataTable, } from "@medusajs/ui"; -import { useMemo, useState } from "react"; +import { useMemo } from "react"; import { useNavigate } from "react-router-dom"; import { usePostsDataTableColumns } from "./use-post-data-table-columns"; import { useAdminListPosts } from "../../../../hooks/posts-queries"; @@ -20,6 +17,7 @@ import { useAdminDeletePost, useAdminDuplicatePost, } from "../../../../hooks/posts-mutations"; +import { usePostTableQuery } from "./use-post-table-query"; // Create filter helper const filterHelper = createDataTableFilterHelper(); @@ -61,17 +59,21 @@ export const PostsDataTable = () => { const { mutateAsync: deletePost } = useAdminDeletePost(); const { mutateAsync: duplicatePost } = useAdminDuplicatePost(); const limit = 10; - const [pagination, setPagination] = useState({ + + // Get all query state from the hook + const { + searchParams, + pagination, + filtering, + sorting, + search, + setPaginationState, + setFilteringState, + setSortingState, + setSearchState, + } = usePostTableQuery({ pageSize: limit, - pageIndex: 0, }); - const [search, setSearch] = useState(""); - const [filtering, setFiltering] = useState({}); - const [sorting, setSorting] = useState(null); - - const offset = useMemo(() => { - return pagination.pageIndex * limit; - }, [pagination]); const statusFilters = useMemo(() => { return (filtering.status || []) as PostStatus[]; @@ -82,19 +84,16 @@ export const PostsDataTable = () => { }, [filtering]); const handleEdit = (id: string) => { - // navigate(`/editor/${post.type}/${post.id}`) navigate("editor/test"); // TODO: change to the actual content detail page }; const handleDuplicate = async (id: string) => { await duplicatePost(id); - toast.success("Page duplicated"); }; const handleDelete = async (id: string) => { await deletePost(id); - toast.success("Page deleted"); }; @@ -105,11 +104,9 @@ export const PostsDataTable = () => { }); const { data, isLoading } = useAdminListPosts({ - limit, - offset, - q: search, - status: statusFilters, - type: typeFilters, + ...searchParams, + status: statusFilters.length > 0 ? statusFilters : undefined, + type: typeFilters.length > 0 ? typeFilters : undefined, order: sorting ? `${sorting.desc ? "-" : ""}${sorting.id}` : undefined, }); @@ -121,20 +118,20 @@ export const PostsDataTable = () => { isLoading, pagination: { state: pagination, - onPaginationChange: setPagination, + onPaginationChange: setPaginationState, }, search: { state: search, - onSearchChange: setSearch, + onSearchChange: setSearchState, }, filtering: { state: filtering, - onFilteringChange: setFiltering, + onFilteringChange: setFilteringState, }, filters, sorting: { state: sorting, - onSortingChange: setSorting, + onSortingChange: setSortingState, }, }); diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-table-query.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-table-query.tsx new file mode 100644 index 00000000..c024744a --- /dev/null +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-table-query.tsx @@ -0,0 +1,211 @@ +import { useQueryParams } from '../../../../hooks/use-query-params'; +import type { AdminPageBuilderListPostsQuery } from '../../../../../sdk/types'; +import type { PostContentMode, PostType, PostStatus } from '../../../../../modules/page-builder/types'; +import { useMemo } from 'react'; +import type { DataTableFilteringState, DataTablePaginationState, DataTableSortingState } from '@medusajs/ui'; + +type UsePostTableQueryProps = { + prefix?: string; + pageSize?: number; +}; + +const DEFAULT_FIELDS = [ + 'id', + 'type', + 'title', + 'handle', + 'excerpt', + 'status', + 'published_at', + 'archived_at', + 'is_home_page', + 'created_at', + 'updated_at', + 'featured_image.*', +].join(','); + +export const usePostTableQuery = ({ prefix, pageSize = 10 }: UsePostTableQueryProps) => { + const { queryObject, setQueryObject } = useQueryParams( + [ + 'offset', + 'order', + 'q', + 'title', + 'handle', + 'status', + 'type', + 'content_mode', + 'is_home_page', + 'published_at', + 'archived_at', + 'created_at', + 'updated_at', + 'id', + ], + prefix, + ); + + const { + offset, + title, + handle, + status, + type, + content_mode, + is_home_page, + published_at, + archived_at, + created_at, + updated_at, + order, + q, + } = queryObject; + + // Derived state for data table + const pagination = useMemo( + () => ({ + pageSize, + pageIndex: offset ? Math.floor(Number(offset) / pageSize) : 0, + }), + [offset, pageSize], + ); + + const filtering = useMemo(() => { + const filterState: DataTableFilteringState = {}; + + if (status) { + filterState.status = status.split(','); + } + + if (type) { + filterState.type = type.split(','); + } + + return filterState; + }, [status, type]); + + const sorting = useMemo(() => { + if (order) { + const isDesc = order.startsWith('-'); + const field = isDesc ? order.substring(1) : order; + return { + id: field, + desc: isDesc, + }; + } + return null; + }, [order]); + + const searchParams: AdminPageBuilderListPostsQuery = { + limit: pageSize, + offset: offset ? Number(offset) : 0, + title: title, + handle: handle, + status: status?.split(',') as PostStatus[], + type: type?.split(',') as PostType[], + content_mode: content_mode?.split(',') as PostContentMode[], + is_home_page: is_home_page ? is_home_page === 'true' : undefined, + published_at: published_at ? JSON.parse(published_at) : undefined, + archived_at: archived_at ? JSON.parse(archived_at) : undefined, + created_at: created_at ? JSON.parse(created_at) : undefined, + updated_at: updated_at ? JSON.parse(updated_at) : undefined, + order: order, + q, + fields: DEFAULT_FIELDS, + }; + + // State updaters + const setSearchParams = (params: Partial) => { + const newQueryObject: Record = {}; + + if ('q' in params) { + newQueryObject.q = params.q || undefined; + } + + if ('status' in params) { + if (params.status && Array.isArray(params.status) && params.status.length > 0) { + newQueryObject.status = params.status.join(','); + } else if (typeof params.status === 'string') { + newQueryObject.status = params.status; + } else { + newQueryObject.status = undefined; + } + } + + if ('type' in params) { + if (params.type && Array.isArray(params.type) && params.type.length > 0) { + newQueryObject.type = params.type.join(','); + } else if (typeof params.type === 'string') { + newQueryObject.type = params.type; + } else { + newQueryObject.type = undefined; + } + } + + if ('content_mode' in params) { + if (params.content_mode && Array.isArray(params.content_mode) && params.content_mode.length > 0) { + newQueryObject.content_mode = params.content_mode.join(','); + } else if (typeof params.content_mode === 'string') { + newQueryObject.content_mode = params.content_mode; + } else { + newQueryObject.content_mode = undefined; + } + } + + if (params.is_home_page !== undefined) { + newQueryObject.is_home_page = params.is_home_page?.toString(); + } + + if (params.order !== undefined) { + newQueryObject.order = params.order || undefined; + } + + if (params.offset !== undefined) { + newQueryObject.offset = params.offset?.toString(); + } + + setQueryObject(newQueryObject); + }; + + // Simplified handlers for common operations + const setPaginationState = (newPagination: DataTablePaginationState) => { + setSearchParams({ offset: newPagination.pageIndex * pageSize }); + }; + + const setFilteringState = (newFiltering: DataTableFilteringState) => { + setSearchParams({ + status: (newFiltering.status || []) as PostStatus[], + type: (newFiltering.type || []) as PostType[], + }); + }; + + const setSortingState = (newSorting: DataTableSortingState | null) => { + if (newSorting) { + setSearchParams({ + order: `${newSorting.desc ? '-' : ''}${newSorting.id}`, + }); + } else { + setSearchParams({ order: undefined }); + } + }; + + const setSearchState = (search: string) => { + setSearchParams({ q: search || undefined }); + }; + + return { + searchParams, + raw: queryObject, + setSearchParams, + // Derived state + pagination, + filtering, + sorting, + search: q || '', + // State updaters + setPaginationState, + setFilteringState, + setSortingState, + setSearchState, + }; +}; From dd75ef0f0d09b4474f9eed1d772888398266be79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Mon, 24 Mar 2025 09:18:22 -0600 Subject: [PATCH 25/28] feat(page-builder-types): add initial type definitions and package configuration - Create package.json for page-builder-types with dependencies and configuration. - Add .gitignore to exclude node_modules. - Define type declarations for posts, storefronts, and common types in TypeScript. - Implement interfaces for paginated responses, post creation, updating, and deletion. - Establish foundational types for post management in the page builder. --- packages/page-builder-types/.gitignore | 1 + packages/page-builder-types/package.json | 18 ++++ packages/page-builder-types/src/admins.d.ts | 78 ++++++++++++++++ packages/page-builder-types/src/common.d.ts | 39 ++++++++ packages/page-builder-types/src/index.d.ts | 4 + packages/page-builder-types/src/models.d.ts | 92 +++++++++++++++++++ .../page-builder-types/src/storefronts.d.ts | 49 ++++++++++ 7 files changed, 281 insertions(+) create mode 100644 packages/page-builder-types/.gitignore create mode 100644 packages/page-builder-types/package.json create mode 100644 packages/page-builder-types/src/admins.d.ts create mode 100644 packages/page-builder-types/src/common.d.ts create mode 100644 packages/page-builder-types/src/index.d.ts create mode 100644 packages/page-builder-types/src/models.d.ts create mode 100644 packages/page-builder-types/src/storefronts.d.ts diff --git a/packages/page-builder-types/.gitignore b/packages/page-builder-types/.gitignore new file mode 100644 index 00000000..b512c09d --- /dev/null +++ b/packages/page-builder-types/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/packages/page-builder-types/package.json b/packages/page-builder-types/package.json new file mode 100644 index 00000000..8665e805 --- /dev/null +++ b/packages/page-builder-types/package.json @@ -0,0 +1,18 @@ +{ + "name": "@lambdacurry/medusa-page-builder-types", + "version": "0.0.4", + "packageManager": "yarn@4.6.0", + "types": "./src/index.d.ts", + "devDependencies": { + "typescript": "5.7.3" + }, + "exports": { + ".": "./src/index.d.ts" + }, + "installConfig": { + "hoistingLimits": "workspaces" + }, + "files": [ + "src" + ] +} diff --git a/packages/page-builder-types/src/admins.d.ts b/packages/page-builder-types/src/admins.d.ts new file mode 100644 index 00000000..1b44f093 --- /dev/null +++ b/packages/page-builder-types/src/admins.d.ts @@ -0,0 +1,78 @@ +import type { Post } from './models' + +// Response Types +export interface PaginatedResponse { + count: number + offset: number + limit: number +} + +export type AdminPageBuilderListPostsQuery = { + offset?: number + limit?: number + q?: string + id?: string | string[] + title?: string + handle?: string + status?: PostStatus | PostStatus[] + type?: PostType | PostType[] + content_mode?: PostContentMode | PostContentMode[] + is_home_page?: boolean + // biome-ignore lint/suspicious/noExplicitAny: medusa infered type + published_at?: any + // biome-ignore lint/suspicious/noExplicitAny: medusa infered type + archived_at?: any + // biome-ignore lint/suspicious/noExplicitAny: medusa infered type + created_at?: any + // biome-ignore lint/suspicious/noExplicitAny: medusa infered type + updated_at?: any + order?: string + fields?: string +} + +export interface AdminPageBuilderListPostsResponse extends PaginatedResponse { + posts: Post[] +} + +export type AdminPageBuilderCreatePostBody = { + title: string + handle?: string + excerpt?: string + content?: Record + status?: PostStatus + type?: PostType + content_mode?: PostContentMode + seo?: Record + is_home_page?: boolean +} + +export interface AdminPageBuilderCreatePostResponse { + post: Post +} + +export type AdminPageBuilderUpdatePostBody = { + id: string + title?: string + handle?: string + excerpt?: string + content?: Record + status?: PostStatus + type?: PostType + content_mode?: PostContentMode + seo?: Record + is_home_page?: boolean +} + +export interface AdminPageBuilderUpdatePostResponse { + post: Post +} + +export interface AdminPageBuilderDeletePostResponse { + id: string + object: string + deleted: boolean +} + +export interface AdminPageBuilderDuplicatePostResponse { + post: Post +} diff --git a/packages/page-builder-types/src/common.d.ts b/packages/page-builder-types/src/common.d.ts new file mode 100644 index 00000000..b57fef77 --- /dev/null +++ b/packages/page-builder-types/src/common.d.ts @@ -0,0 +1,39 @@ +/** + * Common type declarations for page builder + */ + +export type PostStatus = 'draft' | 'published' | 'archived' + +export type PostType = 'page' | 'post' + +export type PostContentMode = 'basic' | 'advanced' + +// These would be defined in the implementation file +export declare const postStatuses: readonly PostStatus[] +export declare const postTypes: readonly PostType[] +export declare const postContentModes: readonly PostContentMode[] + +export interface SortOptions { + sort?: string + order?: 'ASC' | 'DESC' +} + +export interface PaginationOptions { + limit?: number + offset?: number +} + +export interface FilterOptions { + q?: string + [key: string]: unknown +} + +export type QueryOptions = SortOptions & PaginationOptions & FilterOptions + +export interface FindConfig extends QueryOptions { + select?: (keyof T)[] + relations?: string[] + where?: { [K in keyof T]?: T[K] | T[K][] } & { + [key: string]: unknown + } +} diff --git a/packages/page-builder-types/src/index.d.ts b/packages/page-builder-types/src/index.d.ts new file mode 100644 index 00000000..cd043c0b --- /dev/null +++ b/packages/page-builder-types/src/index.d.ts @@ -0,0 +1,4 @@ +export * from './admins' +export * from './common' +export * from './models' +export * from './storefronts' diff --git a/packages/page-builder-types/src/models.d.ts b/packages/page-builder-types/src/models.d.ts new file mode 100644 index 00000000..1e22ad16 --- /dev/null +++ b/packages/page-builder-types/src/models.d.ts @@ -0,0 +1,92 @@ +/** + * Type declarations for page builder models + */ + +import type { PostContentMode, PostStatus, PostType } from './common' + +export interface Base { + id: string + created_at: string + updated_at: string | undefined +} + +export interface Post extends Base { + title: string + handle?: string | null + excerpt?: string | null + content?: Record | null + status: PostStatus + type: PostType + content_mode: PostContentMode + seo?: Record | null + is_home_page: boolean + published_at?: string | null + archived_at?: string | null + featured_image_id?: string + featured_image?: Image + authors?: PostAuthor[] + tags?: PostTag[] + sections?: PostSection[] + root_id?: string + root?: PostTemplate +} + +export interface Image extends Base { + url: string + alt?: string + width?: number + height?: number + mime_type?: string + file_size?: number + metadata?: Record +} + +export interface NavigationItem extends Base { + title: string + url: string + parent_id?: string + parent?: NavigationItem + children?: NavigationItem[] +} + +export interface PostAuthor extends Base { + name: string + bio?: string + posts?: Post[] +} + +export interface PostSection extends Base { + name: string + data?: Record + order: number + post_id?: string + post?: Post + parent_section_id?: string + parent_section?: PostSection + child_sections?: PostSection[] +} + +export interface PostTag extends Base { + name: string + posts?: Post[] +} + +export interface PostTemplate extends Base { + name: string + data?: Record + posts?: Post[] +} + +export interface SiteSettings extends Base { + site_name: string + site_url?: string + logo_id?: string + logo?: Image + favicon_id?: string + favicon?: Image + social_links?: Record + navigation?: Record + custom_css?: string + custom_js?: string + meta_defaults?: Record +} diff --git a/packages/page-builder-types/src/storefronts.d.ts b/packages/page-builder-types/src/storefronts.d.ts new file mode 100644 index 00000000..e6096dab --- /dev/null +++ b/packages/page-builder-types/src/storefronts.d.ts @@ -0,0 +1,49 @@ +/** + * Storefront type declarations for page builder + */ + +import type { Post, PostAuthor, PostTag, SiteSettings } from './models' + +export interface StorefrontGetPostParams { + handle: string +} + +export interface StorefrontGetPostResponse { + post: Post +} + +export interface StorefrontListPostsParams { + limit?: number + offset?: number + type?: string + tag?: string + author?: string + sort?: string + order?: 'asc' | 'desc' +} + +export interface StorefrontListPostsResponse { + posts: Post[] + count: number + offset: number + limit: number +} + +export interface StorefrontGetTagsResponse { + tags: PostTag[] +} + +export interface StorefrontGetAuthorsResponse { + authors: PostAuthor[] +} + +export interface StorefrontGetSiteSettingsResponse { + settings: SiteSettings +} + +export interface StorefrontRenderOptions { + cacheControl?: string + handle?: string + language?: string + preview?: boolean +} From 37933b64d1a8e51136a210599ea6323af28e4054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Mon, 24 Mar 2025 09:19:52 -0600 Subject: [PATCH 26/28] feat(plugins-sdk): update version and add page builder resources - Bump version to 0.0.6-beta.3 in package.json. - Add AdminPageBuilderResource for managing posts in the admin interface. - Introduce StorePageBuilderResource for storefront integration. - Extend ExtendedAdminSDK and ExtendedStorefrontSDK to include page builder resources. - Update dependencies to @medusajs/types and @medusajs/js-sdk version 2.6.1. --- packages/plugins-sdk/package.json | 7 +- .../src/sdk/admin/admin-page-builder.ts | 63 ++++++++++++++++ .../src/sdk/admin/admin-product-reviews.ts | 72 ++++++++++++------- packages/plugins-sdk/src/sdk/admin/index.ts | 19 ++--- packages/plugins-sdk/src/sdk/store/index.ts | 19 +++-- .../src/sdk/store/store-page-builder.ts | 12 ++++ .../src/sdk/store/store-product-reviews.ts | 50 ++++++++----- 7 files changed, 181 insertions(+), 61 deletions(-) create mode 100644 packages/plugins-sdk/src/sdk/admin/admin-page-builder.ts create mode 100644 packages/plugins-sdk/src/sdk/store/store-page-builder.ts diff --git a/packages/plugins-sdk/package.json b/packages/plugins-sdk/package.json index 4ab7bfdd..6ecb7e29 100644 --- a/packages/plugins-sdk/package.json +++ b/packages/plugins-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@lambdacurry/medusa-plugins-sdk", - "version": "0.0.5", + "version": "0.0.6-beta.3", "description": "SDK for Medusa plugins", "author": "Lambda Curry (https://lambdacurry.dev)", "license": "MIT", @@ -38,7 +38,7 @@ "dev:publish": "yalc publish" }, "devDependencies": { - "@medusajs/types": "^2.5.0", + "@medusajs/types": "^2.6.1", "prettier": "^3.2.5", "rimraf": "^6.0.1", "tsup": "^8.0.2", @@ -46,7 +46,8 @@ "yalc": "^1.0.0-pre.53" }, "dependencies": { - "@medusajs/js-sdk": "^2.5.0", + "@lambdacurry/medusa-page-builder-types": "0.0.4", + "@medusajs/js-sdk": "^2.6.1", "@types/express": "^5.0.0", "@types/multer": "^1.4.12", "form-data": "^4.0.2" diff --git a/packages/plugins-sdk/src/sdk/admin/admin-page-builder.ts b/packages/plugins-sdk/src/sdk/admin/admin-page-builder.ts new file mode 100644 index 00000000..ccff26b4 --- /dev/null +++ b/packages/plugins-sdk/src/sdk/admin/admin-page-builder.ts @@ -0,0 +1,63 @@ +import type { Client } from '@medusajs/js-sdk' +import type { + AdminPageBuilderCreatePostBody, + AdminPageBuilderCreatePostResponse, + AdminPageBuilderListPostsQuery, + AdminPageBuilderListPostsResponse, + AdminPageBuilderDeletePostResponse, + AdminPageBuilderUpdatePostBody, + AdminPageBuilderUpdatePostResponse, + AdminPageBuilderDuplicatePostResponse, +} from '@lambdacurry/medusa-page-builder-types' + +export class AdminPageBuilderResource { + constructor(private client: Client) {} + + async listPosts(query: AdminPageBuilderListPostsQuery) { + return this.client.fetch( + '/admin/content/posts', + { + method: 'GET', + query, + }, + ) + } + + async createPost(data: AdminPageBuilderCreatePostBody) { + return this.client.fetch( + '/admin/content/posts', + { + method: 'POST', + body: data, + }, + ) + } + + async updatePost(id: string, data: AdminPageBuilderUpdatePostBody) { + return this.client.fetch( + `/admin/content/posts/${id}`, + { + method: 'PUT', + body: data, + }, + ) + } + + async deletePost(id: string) { + return this.client.fetch( + `/admin/content/posts/${id}`, + { + method: 'DELETE', + }, + ) + } + + async duplicatePost(id: string) { + return this.client.fetch( + `/admin/content/posts/${id}/duplicate`, + { + method: 'POST', + }, + ) + } +} diff --git a/packages/plugins-sdk/src/sdk/admin/admin-product-reviews.ts b/packages/plugins-sdk/src/sdk/admin/admin-product-reviews.ts index 6aac9951..52d7dc18 100644 --- a/packages/plugins-sdk/src/sdk/admin/admin-product-reviews.ts +++ b/packages/plugins-sdk/src/sdk/admin/admin-product-reviews.ts @@ -1,46 +1,70 @@ -import type { Client } from '@medusajs/js-sdk'; +import type { Client } from '@medusajs/js-sdk' import type { AdminCreateProductReviewResponseDTO, AdminListProductReviewsQuery, AdminProductReviewResponse, AdminUpdateProductReviewResponseDTO, AdminListProductReviewsResponse, -} from '../../types'; +} from '../../types' export class AdminProductReviewsResource { constructor(private client: Client) {} async list(query: AdminListProductReviewsQuery) { - return this.client.fetch(`/admin/product-reviews`, { - method: 'GET', - query, - }); + return this.client.fetch( + '/admin/product-reviews', + { + method: 'GET', + query, + }, + ) } - async updateStatus(productReviewId: string, status: 'pending' | 'approved' | 'flagged') { - return this.client.fetch(`/admin/product-reviews/${productReviewId}/status`, { - method: 'PUT', - body: { status }, - }); + async updateStatus( + productReviewId: string, + status: 'pending' | 'approved' | 'flagged', + ) { + return this.client.fetch( + `/admin/product-reviews/${productReviewId}/status`, + { + method: 'PUT', + body: { status }, + }, + ) } - async createResponse(productReviewId: string, data: AdminCreateProductReviewResponseDTO) { - return this.client.fetch(`/admin/product-reviews/${productReviewId}/response`, { - method: 'POST', - body: data, - }); + async createResponse( + productReviewId: string, + data: AdminCreateProductReviewResponseDTO, + ) { + return this.client.fetch( + `/admin/product-reviews/${productReviewId}/response`, + { + method: 'POST', + body: data, + }, + ) } - async updateResponse(productReviewId: string, data: AdminUpdateProductReviewResponseDTO) { - return this.client.fetch(`/admin/product-reviews/${productReviewId}/response`, { - method: 'PUT', - body: data, - }); + async updateResponse( + productReviewId: string, + data: AdminUpdateProductReviewResponseDTO, + ) { + return this.client.fetch( + `/admin/product-reviews/${productReviewId}/response`, + { + method: 'PUT', + body: data, + }, + ) } async deleteResponse(productReviewId: string) { - return this.client.fetch(`/admin/product-reviews/${productReviewId}/response`, { - method: 'DELETE', - }); + return this.client.fetch( + `/admin/product-reviews/${productReviewId}/response`, + { + method: 'DELETE', + }, + ) } } diff --git a/packages/plugins-sdk/src/sdk/admin/index.ts b/packages/plugins-sdk/src/sdk/admin/index.ts index 377d753b..fbb7288a 100644 --- a/packages/plugins-sdk/src/sdk/admin/index.ts +++ b/packages/plugins-sdk/src/sdk/admin/index.ts @@ -1,12 +1,15 @@ -import type { Client } from '@medusajs/js-sdk'; -import { Admin } from '@medusajs/js-sdk'; -import { AdminProductReviewsResource } from './admin-product-reviews'; - +import type { Client } from '@medusajs/js-sdk' +import { Admin } from '@medusajs/js-sdk' +import { AdminProductReviewsResource } from './admin-product-reviews' +import { AdminPageBuilderResource } from './admin-page-builder' export class ExtendedAdminSDK extends Admin { - public productReviews: AdminProductReviewsResource; + public productReviews: AdminProductReviewsResource + public pageBuilder: AdminPageBuilderResource constructor(client: Client) { - super(client); - this.productReviews = new AdminProductReviewsResource(client); + super(client) + + this.productReviews = new AdminProductReviewsResource(client) + this.pageBuilder = new AdminPageBuilderResource(client) } -} \ No newline at end of file +} diff --git a/packages/plugins-sdk/src/sdk/store/index.ts b/packages/plugins-sdk/src/sdk/store/index.ts index 8e1f69a5..e6bbe74e 100644 --- a/packages/plugins-sdk/src/sdk/store/index.ts +++ b/packages/plugins-sdk/src/sdk/store/index.ts @@ -1,11 +1,16 @@ -import type { Client } from '@medusajs/js-sdk'; -import { Store } from '@medusajs/js-sdk'; -import { StoreProductReviewsResource } from './store-product-reviews'; +import type { Client } from '@medusajs/js-sdk' +import { Store } from '@medusajs/js-sdk' +import { StoreProductReviewsResource } from './store-product-reviews' +import { StorePageBuilderResource } from './store-page-builder' export class ExtendedStorefrontSDK extends Store { - public productReviews: StoreProductReviewsResource; + public productReviews: StoreProductReviewsResource + public pageBuilder: StorePageBuilderResource + constructor(client: Client) { - super(client); - this.productReviews = new StoreProductReviewsResource(client); + super(client) + + this.productReviews = new StoreProductReviewsResource(client) + this.pageBuilder = new StorePageBuilderResource(client) } -} \ No newline at end of file +} diff --git a/packages/plugins-sdk/src/sdk/store/store-page-builder.ts b/packages/plugins-sdk/src/sdk/store/store-page-builder.ts new file mode 100644 index 00000000..0ad85f04 --- /dev/null +++ b/packages/plugins-sdk/src/sdk/store/store-page-builder.ts @@ -0,0 +1,12 @@ +import type { Client } from '@medusajs/js-sdk' + +export class StorePageBuilderResource { + constructor(private client: Client) {} + + async test() { + console.log(this.client) + return { + message: 'Hello, world!', + } + } +} diff --git a/packages/plugins-sdk/src/sdk/store/store-product-reviews.ts b/packages/plugins-sdk/src/sdk/store/store-product-reviews.ts index 51d829d1..a3c23c01 100644 --- a/packages/plugins-sdk/src/sdk/store/store-product-reviews.ts +++ b/packages/plugins-sdk/src/sdk/store/store-product-reviews.ts @@ -1,37 +1,49 @@ -import type { Client, ClientHeaders } from '@medusajs/js-sdk'; +import type { Client, ClientHeaders } from '@medusajs/js-sdk' import type { StoreListProductReviewsQuery, StoreListProductReviewsResponse, StoreListProductReviewStatsQuery, StoreListProductReviewStatsResponse, StoreUpsertProductReviewsDTO, - StoreUpsertProductReviewsResponse -} from '../../types'; + StoreUpsertProductReviewsResponse, +} from '../../types' export class StoreProductReviewsResource { constructor(private client: Client) {} async upsert(data: StoreUpsertProductReviewsDTO, headers?: ClientHeaders) { - return this.client.fetch(`/store/product-reviews`, { - method: 'POST', - body: data, - headers, - }); + return this.client.fetch( + '/store/product-reviews', + { + method: 'POST', + body: data, + headers, + }, + ) } async list(query: StoreListProductReviewsQuery, headers?: ClientHeaders) { - return this.client.fetch(`/store/product-reviews`, { - method: 'GET', - query, - headers, - }); + return this.client.fetch( + '/store/product-reviews', + { + method: 'GET', + query, + headers, + }, + ) } - async listStats(query: StoreListProductReviewStatsQuery, headers?: ClientHeaders) { - return this.client.fetch(`/store/product-review-stats`, { - method: 'GET', - query, - headers, - }); + async listStats( + query: StoreListProductReviewStatsQuery, + headers?: ClientHeaders, + ) { + return this.client.fetch( + '/store/product-review-stats', + { + method: 'GET', + query, + headers, + }, + ) } } From f132a758eea392e438a79297dd907ed77a2dc36a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Mon, 24 Mar 2025 09:24:24 -0600 Subject: [PATCH 27/28] feat(page-builder): refactor post management and update dependencies - Update post-related types and workflows to utilize new enum values for post statuses, types, and content modes. - Refactor validations and routes to use updated type imports from @lambdacurry/medusa-page-builder-types. - Remove deprecated common types and SDK files to streamline the codebase. - Bump dependencies in package.json to version 2.6.1 for various Medusa packages. - Introduce new enum-values module for better organization of post-related constants. --- plugins/page-builder/package.json | 22 +- .../admin/content/posts/[id]/middlewares.ts | 1 - .../api/admin/content/posts/[id]/route.tsx | 56 +- .../api/admin/content/posts/middlewares.ts | 1 - .../src/api/admin/content/posts/route.ts | 4 +- .../src/api/admin/content/validations.ts | 19 +- .../src/modules/page-builder/enum-values.ts | 3 + .../src/modules/page-builder/models/post.ts | 12 +- .../src/modules/page-builder/types/common.ts | 27 - .../src/modules/page-builder/types/index.ts | 2 - .../src/sdk/admin/admin-page-builder.ts | 63 -- plugins/page-builder/src/sdk/admin/index.ts | 13 - plugins/page-builder/src/sdk/index.ts | 18 - plugins/page-builder/src/sdk/store/index.ts | 13 - .../src/sdk/store/store-page-builder.ts | 11 - plugins/page-builder/src/sdk/types.ts | 40 - .../page-builder/src/workflows/create-post.ts | 3 +- .../page-builder/src/workflows/delete-post.ts | 2 +- .../src/workflows/duplicate-post.ts | 3 +- .../src/workflows/steps/create-post.ts | 3 +- .../src/workflows/steps/delete-post.ts | 6 +- .../src/workflows/steps/duplicate-post.ts | 3 +- .../src/workflows/steps/update-post.ts | 3 +- .../mutations.ts => workflows/types/index.ts} | 2 +- .../page-builder/src/workflows/update-post.ts | 2 +- yarn.lock | 772 +++++++++--------- 26 files changed, 462 insertions(+), 642 deletions(-) create mode 100644 plugins/page-builder/src/modules/page-builder/enum-values.ts delete mode 100644 plugins/page-builder/src/modules/page-builder/types/common.ts delete mode 100644 plugins/page-builder/src/modules/page-builder/types/index.ts delete mode 100644 plugins/page-builder/src/sdk/admin/admin-page-builder.ts delete mode 100644 plugins/page-builder/src/sdk/admin/index.ts delete mode 100644 plugins/page-builder/src/sdk/index.ts delete mode 100644 plugins/page-builder/src/sdk/store/index.ts delete mode 100644 plugins/page-builder/src/sdk/store/store-page-builder.ts delete mode 100644 plugins/page-builder/src/sdk/types.ts rename plugins/page-builder/src/{modules/page-builder/types/mutations.ts => workflows/types/index.ts} (91%) diff --git a/plugins/page-builder/package.json b/plugins/page-builder/package.json index 112b9c55..93a94153 100644 --- a/plugins/page-builder/package.json +++ b/plugins/page-builder/package.json @@ -36,12 +36,13 @@ "db:generate": "DB_USERNAME=${DB_USERNAME:-postgres} DB_PASSWORD=${DB_PASSWORD:-postgres} medusa plugin:db:generate" }, "devDependencies": { - "@medusajs/admin-sdk": "2.6.0", - "@medusajs/cli": "2.6.0", - "@medusajs/framework": "2.6.0", - "@medusajs/icons": "2.6.0", - "@medusajs/medusa": "2.6.0", - "@medusajs/test-utils": "2.6.0", + "@medusajs/admin-sdk": "^2.6.1", + "@medusajs/cli": "^2.6.1", + "@medusajs/framework": "^2.6.1", + "@medusajs/icons": "^2.6.1", + "@medusajs/medusa": "^2.6.1", + "@medusajs/test-utils": "^2.6.1", + "@medusajs/ui": "^4.0.7", "@mikro-orm/cli": "6.4.3", "@mikro-orm/core": "6.4.3", "@mikro-orm/knex": "6.4.3", @@ -69,7 +70,7 @@ "@medusajs/icons": "^2.6.0", "@medusajs/medusa": "^2.6.0", "@medusajs/test-utils": "^2.6.0", - "@medusajs/ui": "^4.0.6", + "@medusajs/ui": "^4.0.7", "@mikro-orm/cli": "6.4.3", "@mikro-orm/core": "6.4.3", "@mikro-orm/knex": "6.4.3", @@ -85,8 +86,9 @@ "hoistingLimits": "workspaces" }, "dependencies": { - "@lambdacurry/medusa-plugins-sdk": "latest", - "@medusajs/js-sdk": "2.6.0", - "@medusajs/workflows-sdk": "2.6.0" + "@lambdacurry/medusa-page-builder-types": "0.0.4", + "@lambdacurry/medusa-plugins-sdk": "0.0.6-beta.3", + "@medusajs/js-sdk": "^2.6.1", + "@medusajs/workflows-sdk": "^2.6.1" } } diff --git a/plugins/page-builder/src/api/admin/content/posts/[id]/middlewares.ts b/plugins/page-builder/src/api/admin/content/posts/[id]/middlewares.ts index 311f6129..0a1b7355 100644 --- a/plugins/page-builder/src/api/admin/content/posts/[id]/middlewares.ts +++ b/plugins/page-builder/src/api/admin/content/posts/[id]/middlewares.ts @@ -1,4 +1,3 @@ -import { z } from 'zod' import { type MiddlewareRoute, validateAndTransformBody, diff --git a/plugins/page-builder/src/api/admin/content/posts/[id]/route.tsx b/plugins/page-builder/src/api/admin/content/posts/[id]/route.tsx index 3b98ac12..4e5b5f38 100644 --- a/plugins/page-builder/src/api/admin/content/posts/[id]/route.tsx +++ b/plugins/page-builder/src/api/admin/content/posts/[id]/route.tsx @@ -1,38 +1,38 @@ -import { - AuthenticatedMedusaRequest, - MedusaResponse, -} from '@medusajs/framework/http' -import { updatePostWorkflow } from '../../../../../workflows/update-post' -import { deletePostWorkflow } from '../../../../../workflows/delete-post' -import { UpdatePostDTO } from '../../validations' +import type { + AuthenticatedMedusaRequest, + MedusaResponse, +} from "@medusajs/framework/http"; +import { updatePostWorkflow } from "../../../../../workflows/update-post"; +import { deletePostWorkflow } from "../../../../../workflows/delete-post"; +import type { AdminPageBuilderUpdatePostBody } from "@lambdacurry/medusa-page-builder-types"; export const PUT = async ( - req: AuthenticatedMedusaRequest, - res: MedusaResponse, + req: AuthenticatedMedusaRequest, + res: MedusaResponse, ) => { - const id = req.params.id - const data = { ...req.validatedBody, id } + const id = req.params.id; + const data = { ...req.validatedBody, id }; - const { result } = await updatePostWorkflow(req.scope).run({ - input: { - post: data, - }, - }) + const { result } = await updatePostWorkflow(req.scope).run({ + input: { + post: data, + }, + }); - res.status(200).json({ post: result }) -} + res.status(200).json({ post: result }); +}; export const DELETE = async ( - req: AuthenticatedMedusaRequest, - res: MedusaResponse, + req: AuthenticatedMedusaRequest, + res: MedusaResponse, ) => { - const id = req.params.id + const id = req.params.id; - const { result } = await deletePostWorkflow(req.scope).run({ - input: { - id, - }, - }) + const { result } = await deletePostWorkflow(req.scope).run({ + input: { + id, + }, + }); - res.status(200).json({ id: result.id, object: 'post', deleted: true }) -} + res.status(200).json({ id: result.id, object: "post", deleted: true }); +}; diff --git a/plugins/page-builder/src/api/admin/content/posts/middlewares.ts b/plugins/page-builder/src/api/admin/content/posts/middlewares.ts index d7c26fc1..1671360d 100644 --- a/plugins/page-builder/src/api/admin/content/posts/middlewares.ts +++ b/plugins/page-builder/src/api/admin/content/posts/middlewares.ts @@ -1,4 +1,3 @@ -import { z } from 'zod' import { type MiddlewareRoute, validateAndTransformQuery, diff --git a/plugins/page-builder/src/api/admin/content/posts/route.ts b/plugins/page-builder/src/api/admin/content/posts/route.ts index cd0c6375..0b3cf3de 100644 --- a/plugins/page-builder/src/api/admin/content/posts/route.ts +++ b/plugins/page-builder/src/api/admin/content/posts/route.ts @@ -3,7 +3,7 @@ import type { MedusaResponse, } from '@medusajs/framework/http' import { createPostWorkflow } from '../../../../workflows/create-post' -import type { CreatePostDTO } from '../validations' +import type { AdminPageBuilderCreatePostBody } from '@lambdacurry/medusa-page-builder-types' export const GET = async ( req: AuthenticatedMedusaRequest, @@ -28,7 +28,7 @@ export const GET = async ( } export const POST = async ( - req: AuthenticatedMedusaRequest, + req: AuthenticatedMedusaRequest, res: MedusaResponse, ) => { const { result } = await createPostWorkflow(req.scope).run({ diff --git a/plugins/page-builder/src/api/admin/content/validations.ts b/plugins/page-builder/src/api/admin/content/validations.ts index 01807366..ed0b4d1a 100644 --- a/plugins/page-builder/src/api/admin/content/validations.ts +++ b/plugins/page-builder/src/api/admin/content/validations.ts @@ -5,14 +5,14 @@ import { } from '@medusajs/medusa/api/utils/validators' import { - postContentModes, - postStatuses, - postTypes, -} from '../../../modules/page-builder/types' + postStatusValues, + postTypeValues, + postContentModeValues, +} from '../../../modules/page-builder/enum-values' -const postStatusesEnum = z.enum([...postStatuses]) -const postTypesEnum = z.enum([...postTypes]) -const postContentModesEnum = z.enum([...postContentModes]) +export const postStatusesEnum = z.enum([...postStatusValues]) +export const postTypesEnum = z.enum([...postTypeValues]) +export const postContentModesEnum = z.enum([...postContentModeValues]) export const createPostSchema = z.object({ title: z.string(), @@ -64,8 +64,3 @@ export const listAdminPostsQuerySchema = createFindParams({ updated_at: createOperatorMap().optional(), }), ) - -export type CreatePostDTO = z.infer -export type UpdatePostDTO = z.infer -export type DeletePostDTO = z.infer -export type ListAdminPostsQueryDTO = z.infer diff --git a/plugins/page-builder/src/modules/page-builder/enum-values.ts b/plugins/page-builder/src/modules/page-builder/enum-values.ts new file mode 100644 index 00000000..23e58f55 --- /dev/null +++ b/plugins/page-builder/src/modules/page-builder/enum-values.ts @@ -0,0 +1,3 @@ +export const postTypeValues = ['page', 'post'] as const +export const postStatusValues = ['draft', 'published', 'archived'] as const +export const postContentModeValues = ['basic', 'advanced'] as const diff --git a/plugins/page-builder/src/modules/page-builder/models/post.ts b/plugins/page-builder/src/modules/page-builder/models/post.ts index 10adb945..d16f5169 100644 --- a/plugins/page-builder/src/modules/page-builder/models/post.ts +++ b/plugins/page-builder/src/modules/page-builder/models/post.ts @@ -3,17 +3,21 @@ import { PostSectionModel } from './post-section' import { PostTagModel } from './post-tag' import { PostAuthorModel } from './post-author' import { ImageModel } from './image' -import { postContentModes, postStatuses, postTypes } from '../types/common' +import { + postContentModeValues, + postStatusValues, + postTypeValues, +} from '../enum-values' export const PostModel = model.define('post', { id: model.id({ prefix: 'post' }).primaryKey(), - type: model.enum([...postTypes]), + type: model.enum([...postTypeValues]), title: model.text().searchable(), handle: model.text().unique().searchable().nullable(), excerpt: model.text().searchable().nullable(), content: model.json().nullable(), - status: model.enum([...postStatuses]).default('draft'), - content_mode: model.enum([...postContentModes]).default('advanced'), + status: model.enum([...postStatusValues]).default('draft'), + content_mode: model.enum([...postContentModeValues]).default('advanced'), seo: model.json().nullable(), published_at: model.text().nullable(), archived_at: model.text().nullable(), diff --git a/plugins/page-builder/src/modules/page-builder/types/common.ts b/plugins/page-builder/src/modules/page-builder/types/common.ts deleted file mode 100644 index 5244df11..00000000 --- a/plugins/page-builder/src/modules/page-builder/types/common.ts +++ /dev/null @@ -1,27 +0,0 @@ -import type { InferTypeOf } from '@medusajs/framework/types' - -import { PostModel } from '../models/post' -import { PostAuthorModel } from '../models/post-author' -import { PostTagModel } from '../models/post-tag' -import { PostSectionModel } from '../models/post-section' -import { PostTemplateModel } from '../models/post-template' -import { ImageModel } from '../models/image' -import { SiteSettingsModel } from '../models/site-settings' -import { NavigationItemModel } from '../models/navigation-item' - -export const postTypes = ['page', 'post'] as const -export const postStatuses = ['draft', 'published', 'archived'] as const -export const postContentModes = ['basic', 'advanced'] as const - -export type PostType = (typeof postTypes)[number] -export type PostStatus = (typeof postStatuses)[number] -export type PostContentMode = (typeof postContentModes)[number] - -export type Post = InferTypeOf -export type PostAuthor = InferTypeOf -export type PostTag = InferTypeOf -export type PostSection = InferTypeOf -export type PostTemplate = InferTypeOf -export type Image = InferTypeOf -export type SiteSettings = InferTypeOf -export type NavigationItem = InferTypeOf diff --git a/plugins/page-builder/src/modules/page-builder/types/index.ts b/plugins/page-builder/src/modules/page-builder/types/index.ts deleted file mode 100644 index a2ab5bce..00000000 --- a/plugins/page-builder/src/modules/page-builder/types/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './common' -export * from './mutations' diff --git a/plugins/page-builder/src/sdk/admin/admin-page-builder.ts b/plugins/page-builder/src/sdk/admin/admin-page-builder.ts deleted file mode 100644 index 7f28974e..00000000 --- a/plugins/page-builder/src/sdk/admin/admin-page-builder.ts +++ /dev/null @@ -1,63 +0,0 @@ -import type { Client } from '@medusajs/js-sdk' -import type { - AdminPageBuilderCreatePostBody, - AdminPageBuilderCreatePostResponse, - AdminPageBuilderListPostsQuery, - AdminPageBuilderListPostsResponse, - AdminPageBuilderDeletePostResponse, - AdminPageBuilderUpdatePostBody, - AdminPageBuilderUpdatePostResponse, - AdminPageBuilderDuplicatePostResponse, -} from '../types' - -export class AdminPageBuilderResource { - constructor(private client: Client) {} - - async listPosts(query: AdminPageBuilderListPostsQuery) { - return this.client.fetch( - '/admin/content/posts', - { - method: 'GET', - query, - }, - ) - } - - async createPost(data: AdminPageBuilderCreatePostBody) { - return this.client.fetch( - '/admin/content/posts', - { - method: 'POST', - body: data, - }, - ) - } - - async updatePost(id: string, data: AdminPageBuilderUpdatePostBody) { - return this.client.fetch( - `/admin/content/posts/${id}`, - { - method: 'PUT', - body: data, - }, - ) - } - - async deletePost(id: string) { - return this.client.fetch( - `/admin/content/posts/${id}`, - { - method: 'DELETE', - }, - ) - } - - async duplicatePost(id: string) { - return this.client.fetch( - `/admin/content/posts/${id}/duplicate`, - { - method: 'POST', - }, - ) - } -} diff --git a/plugins/page-builder/src/sdk/admin/index.ts b/plugins/page-builder/src/sdk/admin/index.ts deleted file mode 100644 index fee272db..00000000 --- a/plugins/page-builder/src/sdk/admin/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Client } from '@medusajs/js-sdk' -import { Admin as MedusaAdmin } from '@medusajs/js-sdk' -import { AdminPageBuilderResource } from './admin-page-builder' - -export class ExtendedAdmin extends MedusaAdmin { - public pageBuilder: AdminPageBuilderResource - - constructor(client: Client) { - super(client) - - this.pageBuilder = new AdminPageBuilderResource(client) - } -} diff --git a/plugins/page-builder/src/sdk/index.ts b/plugins/page-builder/src/sdk/index.ts deleted file mode 100644 index 532afb74..00000000 --- a/plugins/page-builder/src/sdk/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import Medusa, { type Config } from '@medusajs/js-sdk' -import { ExtendedAdmin } from './admin' -import { ExtendedStore } from './store' - -export class ExtendedMedusaSDK extends Medusa { - public admin: ExtendedAdmin - public store: ExtendedStore - - constructor(config: Config) { - super(config) - - this.admin = new ExtendedAdmin(this.client) - this.store = new ExtendedStore(this.client) - } -} - -export { AdminPageBuilderResource } from './admin/admin-page-builder' -export { StorePageBuilderResource } from './store/store-page-builder' diff --git a/plugins/page-builder/src/sdk/store/index.ts b/plugins/page-builder/src/sdk/store/index.ts deleted file mode 100644 index f3965048..00000000 --- a/plugins/page-builder/src/sdk/store/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { Client } from '@medusajs/js-sdk' -import { Store as MedusaStore } from '@medusajs/js-sdk' -import { StorePageBuilderResource } from './store-page-builder' - -export class ExtendedStore extends MedusaStore { - public pageBuilder: StorePageBuilderResource - - constructor(client: Client) { - super(client) - - this.pageBuilder = new StorePageBuilderResource(client) - } -} diff --git a/plugins/page-builder/src/sdk/store/store-page-builder.ts b/plugins/page-builder/src/sdk/store/store-page-builder.ts deleted file mode 100644 index d7e98de9..00000000 --- a/plugins/page-builder/src/sdk/store/store-page-builder.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { Client, ClientHeaders } from '@medusajs/js-sdk' - -export class StorePageBuilderResource { - constructor(private client: Client) {} - - // async getPost(postId: string) { - // return this.client.fetch(`/store/content/posts/${postId}`, { - // method: 'GET', - // }); - // } -} diff --git a/plugins/page-builder/src/sdk/types.ts b/plugins/page-builder/src/sdk/types.ts deleted file mode 100644 index 27797d5c..00000000 --- a/plugins/page-builder/src/sdk/types.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { Post } from '../modules/page-builder/types' -import type { - CreatePostDTO, - ListAdminPostsQueryDTO, - UpdatePostDTO, -} from '../api/admin/content/validations' - -interface PaginatedResponse { - count: number - offset: number - limit: number -} - -export type AdminPageBuilderListPostsQuery = ListAdminPostsQueryDTO - -export interface AdminPageBuilderListPostsResponse extends PaginatedResponse { - posts: Post[] -} - -export type AdminPageBuilderCreatePostBody = CreatePostDTO - -export type AdminPageBuilderCreatePostResponse = { - post: Post -} - -export type AdminPageBuilderUpdatePostBody = UpdatePostDTO - -export type AdminPageBuilderUpdatePostResponse = { - post: Post -} - -export type AdminPageBuilderDeletePostResponse = { - id: string - object: string - deleted: boolean -} - -export type AdminPageBuilderDuplicatePostResponse = { - post: Post -} diff --git a/plugins/page-builder/src/workflows/create-post.ts b/plugins/page-builder/src/workflows/create-post.ts index bf43cf71..bb4604d9 100644 --- a/plugins/page-builder/src/workflows/create-post.ts +++ b/plugins/page-builder/src/workflows/create-post.ts @@ -1,8 +1,9 @@ import { transform } from '@medusajs/framework/workflows-sdk' import { emitEventStep } from '@medusajs/medusa/core-flows' import { WorkflowResponse, createWorkflow } from '@medusajs/workflows-sdk' + +import type { CreatePostWorkflowInput } from './types' import { pageBuilderModuleEvents } from '../modules/page-builder' -import { CreatePostWorkflowInput } from '../modules/page-builder/types' import { createPostStep } from './steps/create-post' export const createPostWorkflow = createWorkflow( diff --git a/plugins/page-builder/src/workflows/delete-post.ts b/plugins/page-builder/src/workflows/delete-post.ts index 7f94d887..1d2c910d 100644 --- a/plugins/page-builder/src/workflows/delete-post.ts +++ b/plugins/page-builder/src/workflows/delete-post.ts @@ -2,8 +2,8 @@ import { transform } from '@medusajs/framework/workflows-sdk' import { emitEventStep } from '@medusajs/medusa/core-flows' import { WorkflowResponse, createWorkflow } from '@medusajs/workflows-sdk' +import type { DeletePostWorkflowInput } from './types' import { pageBuilderModuleEvents } from '../modules/page-builder' -import { DeletePostWorkflowInput } from '../modules/page-builder/types' import { deletePostStep } from './steps/delete-post' // Delete post workflow diff --git a/plugins/page-builder/src/workflows/duplicate-post.ts b/plugins/page-builder/src/workflows/duplicate-post.ts index 7dc54f24..7dc64ea8 100644 --- a/plugins/page-builder/src/workflows/duplicate-post.ts +++ b/plugins/page-builder/src/workflows/duplicate-post.ts @@ -1,8 +1,9 @@ import { transform } from '@medusajs/framework/workflows-sdk' import { emitEventStep } from '@medusajs/medusa/core-flows' import { WorkflowResponse, createWorkflow } from '@medusajs/workflows-sdk' + +import type { DuplicatePostWorkflowInput } from './types' import { pageBuilderModuleEvents } from '../modules/page-builder' -import type { DuplicatePostWorkflowInput } from '../modules/page-builder/types' import { duplicatePostStep } from './steps/duplicate-post' import { duplicatePostRelationsStep } from './steps/duplicate-post-relations' diff --git a/plugins/page-builder/src/workflows/steps/create-post.ts b/plugins/page-builder/src/workflows/steps/create-post.ts index fb554bcd..93507a03 100644 --- a/plugins/page-builder/src/workflows/steps/create-post.ts +++ b/plugins/page-builder/src/workflows/steps/create-post.ts @@ -1,7 +1,8 @@ import { StepResponse, createStep } from '@medusajs/workflows-sdk' + +import type { CreatePostStepInput } from '../types' import { PAGE_BUILDER_MODULE } from '../../modules/page-builder' import type PageBuilderService from '../../modules/page-builder/service' -import type { CreatePostStepInput } from '../../modules/page-builder/types' export const createPostStepId = 'create-post-step' diff --git a/plugins/page-builder/src/workflows/steps/delete-post.ts b/plugins/page-builder/src/workflows/steps/delete-post.ts index 4c14db69..b292731a 100644 --- a/plugins/page-builder/src/workflows/steps/delete-post.ts +++ b/plugins/page-builder/src/workflows/steps/delete-post.ts @@ -1,10 +1,8 @@ import { StepResponse, createStep } from '@medusajs/workflows-sdk' + +import type { CreatePostStepInput, DeletePostStepInput } from '../types' import { PAGE_BUILDER_MODULE } from '../../modules/page-builder' import type PageBuilderService from '../../modules/page-builder/service' -import type { - CreatePostStepInput, - DeletePostStepInput, -} from '../../modules/page-builder/types' export const deletePostStepId = 'delete-post-step' diff --git a/plugins/page-builder/src/workflows/steps/duplicate-post.ts b/plugins/page-builder/src/workflows/steps/duplicate-post.ts index 1da9f3e9..5ded7251 100644 --- a/plugins/page-builder/src/workflows/steps/duplicate-post.ts +++ b/plugins/page-builder/src/workflows/steps/duplicate-post.ts @@ -1,7 +1,8 @@ import { StepResponse, createStep } from '@medusajs/workflows-sdk' + +import type { DuplicatePostStepInput } from '../types' import { PAGE_BUILDER_MODULE } from '../../modules/page-builder' import type PageBuilderService from '../../modules/page-builder/service' -import type { DuplicatePostStepInput } from '../../modules/page-builder/types' export const duplicatePostStepId = 'duplicate-post-step' diff --git a/plugins/page-builder/src/workflows/steps/update-post.ts b/plugins/page-builder/src/workflows/steps/update-post.ts index f8a2269e..24c77174 100644 --- a/plugins/page-builder/src/workflows/steps/update-post.ts +++ b/plugins/page-builder/src/workflows/steps/update-post.ts @@ -1,7 +1,8 @@ import { StepResponse, createStep } from '@medusajs/workflows-sdk' + +import type { UpdatePostStepInput } from '../types' import { PAGE_BUILDER_MODULE } from '../../modules/page-builder' import type PageBuilderService from '../../modules/page-builder/service' -import type { UpdatePostStepInput } from '../../modules/page-builder/types' export const updatePostStepId = 'update-post-step' diff --git a/plugins/page-builder/src/modules/page-builder/types/mutations.ts b/plugins/page-builder/src/workflows/types/index.ts similarity index 91% rename from plugins/page-builder/src/modules/page-builder/types/mutations.ts rename to plugins/page-builder/src/workflows/types/index.ts index 5cae9d14..817e88fd 100644 --- a/plugins/page-builder/src/modules/page-builder/types/mutations.ts +++ b/plugins/page-builder/src/workflows/types/index.ts @@ -1,4 +1,4 @@ -import type { Post, Image } from './common' +import type { Post } from '@lambdacurry/medusa-page-builder-types' type PostInput = Omit< Post, diff --git a/plugins/page-builder/src/workflows/update-post.ts b/plugins/page-builder/src/workflows/update-post.ts index 82db3546..bfedc505 100644 --- a/plugins/page-builder/src/workflows/update-post.ts +++ b/plugins/page-builder/src/workflows/update-post.ts @@ -2,8 +2,8 @@ import { transform } from '@medusajs/framework/workflows-sdk' import { emitEventStep } from '@medusajs/medusa/core-flows' import { WorkflowResponse, createWorkflow } from '@medusajs/workflows-sdk' +import type { UpdatePostWorkflowInput } from './types' import { pageBuilderModuleEvents } from '../modules/page-builder' -import { UpdatePostWorkflowInput } from '../modules/page-builder/types' import { updatePostStep } from './steps/update-post' export const updatePostWorkflow = createWorkflow( diff --git a/yarn.lock b/yarn.lock index b08990ba..c2516b58 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1854,19 +1854,29 @@ __metadata: languageName: node linkType: hard +"@lambdacurry/medusa-page-builder-types@npm:0.0.4, @lambdacurry/medusa-page-builder-types@workspace:packages/page-builder-types": + version: 0.0.0-use.local + resolution: "@lambdacurry/medusa-page-builder-types@workspace:packages/page-builder-types" + dependencies: + typescript: "npm:5.7.3" + languageName: unknown + linkType: soft + "@lambdacurry/medusa-page-builder@workspace:plugins/page-builder": version: 0.0.0-use.local resolution: "@lambdacurry/medusa-page-builder@workspace:plugins/page-builder" dependencies: - "@lambdacurry/medusa-plugins-sdk": "npm:latest" - "@medusajs/admin-sdk": "npm:2.6.0" - "@medusajs/cli": "npm:2.6.0" - "@medusajs/framework": "npm:2.6.0" - "@medusajs/icons": "npm:2.6.0" - "@medusajs/js-sdk": "npm:2.6.0" - "@medusajs/medusa": "npm:2.6.0" - "@medusajs/test-utils": "npm:2.6.0" - "@medusajs/workflows-sdk": "npm:2.6.0" + "@lambdacurry/medusa-page-builder-types": "npm:0.0.4" + "@lambdacurry/medusa-plugins-sdk": "npm:0.0.6-beta.3" + "@medusajs/admin-sdk": "npm:^2.6.1" + "@medusajs/cli": "npm:^2.6.1" + "@medusajs/framework": "npm:^2.6.1" + "@medusajs/icons": "npm:^2.6.1" + "@medusajs/js-sdk": "npm:^2.6.1" + "@medusajs/medusa": "npm:^2.6.1" + "@medusajs/test-utils": "npm:^2.6.1" + "@medusajs/ui": "npm:^4.0.7" + "@medusajs/workflows-sdk": "npm:^2.6.1" "@mikro-orm/cli": "npm:6.4.3" "@mikro-orm/core": "npm:6.4.3" "@mikro-orm/knex": "npm:6.4.3" @@ -1893,7 +1903,7 @@ __metadata: "@medusajs/icons": ^2.6.0 "@medusajs/medusa": ^2.6.0 "@medusajs/test-utils": ^2.6.0 - "@medusajs/ui": ^4.0.6 + "@medusajs/ui": ^4.0.7 "@mikro-orm/cli": 6.4.3 "@mikro-orm/core": 6.4.3 "@mikro-orm/knex": 6.4.3 @@ -1904,7 +1914,7 @@ __metadata: languageName: unknown linkType: soft -"@lambdacurry/medusa-plugins-sdk@npm:0.0.5, @lambdacurry/medusa-plugins-sdk@npm:latest": +"@lambdacurry/medusa-plugins-sdk@npm:0.0.5": version: 0.0.5 resolution: "@lambdacurry/medusa-plugins-sdk@npm:0.0.5" dependencies: @@ -1916,12 +1926,13 @@ __metadata: languageName: node linkType: hard -"@lambdacurry/medusa-plugins-sdk@workspace:packages/plugins-sdk": +"@lambdacurry/medusa-plugins-sdk@npm:0.0.6-beta.3, @lambdacurry/medusa-plugins-sdk@workspace:packages/plugins-sdk": version: 0.0.0-use.local resolution: "@lambdacurry/medusa-plugins-sdk@workspace:packages/plugins-sdk" dependencies: - "@medusajs/js-sdk": "npm:^2.5.0" - "@medusajs/types": "npm:^2.5.0" + "@lambdacurry/medusa-page-builder-types": "npm:0.0.4" + "@medusajs/js-sdk": "npm:^2.6.1" + "@medusajs/types": "npm:^2.6.1" "@types/express": "npm:^5.0.0" "@types/multer": "npm:^1.4.12" form-data: "npm:^4.0.2" @@ -2045,13 +2056,13 @@ __metadata: languageName: unknown linkType: soft -"@medusajs/admin-bundler@npm:^2.5.0, @medusajs/admin-bundler@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/admin-bundler@npm:2.6.0" +"@medusajs/admin-bundler@npm:2.6.1, @medusajs/admin-bundler@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/admin-bundler@npm:2.6.1" dependencies: - "@medusajs/admin-shared": "npm:2.6.0" - "@medusajs/admin-vite-plugin": "npm:2.6.0" - "@medusajs/dashboard": "npm:2.6.0" + "@medusajs/admin-shared": "npm:2.6.1" + "@medusajs/admin-vite-plugin": "npm:2.6.1" + "@medusajs/dashboard": "npm:2.6.1" "@rollup/plugin-node-resolve": "npm:^16.0.0" "@vitejs/plugin-react": "npm:^4.2.1" autoprefixer: "npm:^10.4.16" @@ -2064,7 +2075,7 @@ __metadata: vite: "npm:^5.4.14" peerDependencies: react-dom: ^18.0.0 - checksum: 10c0/e18125f54b326214fd219c9ec0856460e95220c95347f2158cb7f92ed5d2d60dabedab57a785dde2567b4a9d7c2fb4a4b78e3137f87b2eb556c500581332cc51 + checksum: 10c0/957d73bb6400fd2e1e384a480c5b8f38fc57b096555327bcee195f8283bbe4a262cf2570300c773258642fa10c253d13efa83239c44534d5cb6e577936506850 languageName: node linkType: hard @@ -2111,13 +2122,13 @@ __metadata: languageName: node linkType: hard -"@medusajs/admin-sdk@npm:2.6.0": - version: 2.6.0 - resolution: "@medusajs/admin-sdk@npm:2.6.0" +"@medusajs/admin-sdk@npm:^2.6.1": + version: 2.6.1 + resolution: "@medusajs/admin-sdk@npm:2.6.1" dependencies: - "@medusajs/admin-shared": "npm:^2.6.0" + "@medusajs/admin-shared": "npm:2.6.1" zod: "npm:3.22.4" - checksum: 10c0/22d268882daf0ec5a7c5b6c82ac39b0fc0984d2e5bcd0d7f3ca3e141f22889b4c533c1f560c167d34eab05d73eaabb8ad0c525ee5a0dc379f4eeb330f2b669c0 + checksum: 10c0/ab650456aaa15e3a8731af3f02c2663c8ff03ddb5b57333c4c03e14ef04b309970450a518b6e00a91ede403b0d4b86b8f6591ac98be614ea1afd8b3d6b56f48c languageName: node linkType: hard @@ -2128,10 +2139,10 @@ __metadata: languageName: node linkType: hard -"@medusajs/admin-shared@npm:2.6.0, @medusajs/admin-shared@npm:^2.5.0, @medusajs/admin-shared@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/admin-shared@npm:2.6.0" - checksum: 10c0/330f6ca753ea49f3e9f40d1b2aef01dab6615add227fa5287954ab12185889f1ec4d84f5194bf3c345004156e19bea80b6ef7fab23d62f937fb2eab40d103955 +"@medusajs/admin-shared@npm:2.6.1, @medusajs/admin-shared@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/admin-shared@npm:2.6.1" + checksum: 10c0/35b822c028da1aac1aea48cacf2b629ce771a04f0d3bb1e6d3b44e5df7949fc10bbf1ff2f9bed27023a7cf0ed0afe1ba0150fac00b67e9f4eca1544b04eb94f7 languageName: node linkType: hard @@ -2154,14 +2165,14 @@ __metadata: languageName: node linkType: hard -"@medusajs/admin-vite-plugin@npm:2.6.0": - version: 2.6.0 - resolution: "@medusajs/admin-vite-plugin@npm:2.6.0" +"@medusajs/admin-vite-plugin@npm:2.6.1": + version: 2.6.1 + resolution: "@medusajs/admin-vite-plugin@npm:2.6.1" dependencies: "@babel/parser": "npm:7.25.6" "@babel/traverse": "npm:7.25.6" "@babel/types": "npm:7.25.6" - "@medusajs/admin-shared": "npm:2.6.0" + "@medusajs/admin-shared": "npm:2.6.1" chokidar: "npm:3.5.3" fdir: "npm:6.1.1" magic-string: "npm:0.30.5" @@ -2169,20 +2180,20 @@ __metadata: picocolors: "npm:^1.1.0" peerDependencies: vite: ^5.0.0 - checksum: 10c0/d7f911723cc8f0b446d1a3a2470d64a2301fc963422cbb54fd3024c64da60e2f54d33dda6d36c7f768534970bd203157a8c41ccf431b8e598d4ef60485340a57 + checksum: 10c0/355665d7afb32241d72929fecbfc214f409d579507528c3407af0289d863cd986f2d5970db405b10f95d46a3b76be0dfa408cbf03e3f4e36df80f301e75f677e languageName: node linkType: hard -"@medusajs/api-key@npm:^2.5.0, @medusajs/api-key@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/api-key@npm:2.6.0" +"@medusajs/api-key@npm:2.6.1, @medusajs/api-key@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/api-key@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/46d6198db2e890d5796b34b4363b2bfe4f092eb04edd2883c5533cd289a01eb228481fb999c11add6c291d5f74fc40ac5297e40747ca9b49e244bda0051bf695 + checksum: 10c0/90c7b79aaf8c0a3be05e60fd1fbd380ee8a06ceddd7cefc8baa5d0b3dff1b6176f6fb22a4e2098124f846bb22f63528c4571902e05151e5d9cd3f830fc5fc8db languageName: node linkType: hard @@ -2199,14 +2210,14 @@ __metadata: languageName: node linkType: hard -"@medusajs/auth-emailpass@npm:^2.5.0, @medusajs/auth-emailpass@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/auth-emailpass@npm:2.6.0" +"@medusajs/auth-emailpass@npm:2.6.1, @medusajs/auth-emailpass@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/auth-emailpass@npm:2.6.1" dependencies: scrypt-kdf: "npm:^2.0.1" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/d065dd1edbff7163adc980499e6eb219990fec4af5151161b90ff0a355da75f361b7ade1dfb7cbbfc404f22afdca1edba68525acaeb29ac462dfa35daf516dc1 + "@medusajs/framework": 2.6.1 + checksum: 10c0/f054377f46333a033717871839cd366f006ff17a831c5f7ea3d5484293fa9dec94e7a1280838086c96c1a9d23a360602e285fc988ed8be8659b0a3c18b50efb5 languageName: node linkType: hard @@ -2221,12 +2232,12 @@ __metadata: languageName: node linkType: hard -"@medusajs/auth-github@npm:^2.5.0, @medusajs/auth-github@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/auth-github@npm:2.6.0" +"@medusajs/auth-github@npm:2.6.1, @medusajs/auth-github@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/auth-github@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/027ea828dab54e2d2c02fb9a3c73dbe45dec782c1c2aa9fca100ed82a2aedd58417e178897b6939cf100ee62939af46293d2241aabfcb980a689b24db247b311 + "@medusajs/framework": 2.6.1 + checksum: 10c0/e776f88e7e50713fd8c8ebb9df66a27aceaa2def3ce2e89eb1239515dc4ef195361d0d08415f0b48fad3c9910562fb5244e616a6f361defe667ada3ffce220bd languageName: node linkType: hard @@ -2239,14 +2250,14 @@ __metadata: languageName: node linkType: hard -"@medusajs/auth-google@npm:^2.5.0, @medusajs/auth-google@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/auth-google@npm:2.6.0" +"@medusajs/auth-google@npm:2.6.1, @medusajs/auth-google@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/auth-google@npm:2.6.1" dependencies: jsonwebtoken: "npm:^9.0.2" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/c66e549b8b287ac41020ab86ec37ec66ccd57e79666e0dea8f170b019b6c9b45244800defa7b93d05c5d47522e9f1e273e9fc9baa1a2d0cf62bd1051fe3becfd + "@medusajs/framework": 2.6.1 + checksum: 10c0/d553907adbb9dbaa7751083e2e62f9808438e36b5dae7c26e935a057722854caa0eb5d55ae0badc9faf63a1569af72a1146c567fe954d646d45c5d4c2338fbb0 languageName: node linkType: hard @@ -2261,16 +2272,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/auth@npm:^2.5.0, @medusajs/auth@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/auth@npm:2.6.0" +"@medusajs/auth@npm:2.6.1, @medusajs/auth@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/auth@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/fbf700f4aefc9392579d7b625c1baa6c2bb631a45c55384e36ec93de6e9d0e91cf69b110a5e1d620792412d78a0929df7d69b1135bac67f902571b08bbde3313 + checksum: 10c0/00f9ed5a8bba868630628c28458d89967e0495a168675ab70766d7fccdbe680491ef5209e2698145770ec443c4da84360373069b4a291ee739052704cd6d42d5 languageName: node linkType: hard @@ -2287,12 +2298,12 @@ __metadata: languageName: node linkType: hard -"@medusajs/cache-inmemory@npm:^2.5.0, @medusajs/cache-inmemory@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/cache-inmemory@npm:2.6.0" +"@medusajs/cache-inmemory@npm:2.6.1, @medusajs/cache-inmemory@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/cache-inmemory@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/53c00859bb165f9de608f1e5accad8f4e4a3e467674f54509a74233cce3d81833be7661beecbc658d11f8e8668e30923bd413ea1aece1e09983f15619788d245 + "@medusajs/framework": 2.6.1 + checksum: 10c0/2b7502cb661094abf8614afaa7ddbf1c91d7f61633271816777275338039f236088ce807df392e2afa5b5f93948928fdb8541b1ca440cca6b952d3d74431e9b8 languageName: node linkType: hard @@ -2305,15 +2316,15 @@ __metadata: languageName: node linkType: hard -"@medusajs/cache-redis@npm:^2.5.0, @medusajs/cache-redis@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/cache-redis@npm:2.6.0" +"@medusajs/cache-redis@npm:2.6.1, @medusajs/cache-redis@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/cache-redis@npm:2.6.1" dependencies: ioredis: "npm:^5.4.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 awilix: ^8.0.1 - checksum: 10c0/4b6b629ae598b347a4b1df07c0e7b1fa5a3ff7df6df561f05ad69310293799861f5764def4d3715b6ecb1ebb1d190a042f722d5c90942ca2698eb85653f8bd78 + checksum: 10c0/8f61658c161f49793021ad5989444334f4c0e678e94374f3546ee10bd28206a698ad3c1c31655b69466e8509528aa17a5e186c2fb1114cfd8eab7d2b7c2893d2 languageName: node linkType: hard @@ -2329,16 +2340,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/cart@npm:^2.5.0, @medusajs/cart@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/cart@npm:2.6.0" +"@medusajs/cart@npm:2.6.1, @medusajs/cart@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/cart@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/30282f53513e2c6050b5a49b22d3429002ed77a51e046be925efba2a049ee5d57d02f75317617ef6540fbdf54dacb9dfbc9c13f6c815bbec053bdf3282d74b63 + checksum: 10c0/9d952c1b417ac705f5955a10916728d8e113b3729c63fc84de6ca277c51064f8e5ca32372b8bf5ea42268f358c984106fa77ec0075bfca761104767e91b3a1fe languageName: node linkType: hard @@ -2437,12 +2448,12 @@ __metadata: languageName: node linkType: hard -"@medusajs/cli@npm:2.6.0": - version: 2.6.0 - resolution: "@medusajs/cli@npm:2.6.0" +"@medusajs/cli@npm:^2.6.1": + version: 2.6.1 + resolution: "@medusajs/cli@npm:2.6.1" dependencies: - "@medusajs/telemetry": "npm:^2.6.0" - "@medusajs/utils": "npm:2.6.0" + "@medusajs/telemetry": "npm:2.6.1" + "@medusajs/utils": "npm:2.6.1" "@types/express": "npm:^4.17.17" chalk: "npm:^4.0.0" configstore: "npm:5.0.1" @@ -2474,19 +2485,19 @@ __metadata: pg: ^8.13.0 bin: medusa: cli.js - checksum: 10c0/44c50f167a7907ed3d50a24f4a4f273725b2acd75c341e35a8f143642d93036b313a2edc3a903427340f2a442cfd6b77dc85c31890ae0c54f05a4639b179b9b5 + checksum: 10c0/0420a36df6dcb7dbabe9ce8ba57a1ce21981b30019c01d60c2f1b4cb7c838d342c607c56865d99d359dfe1e0274d73ac7d6a478b72e48f10bd9d32ea13dfa5f1 languageName: node linkType: hard -"@medusajs/core-flows@npm:^2.5.0, @medusajs/core-flows@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/core-flows@npm:2.6.0" +"@medusajs/core-flows@npm:2.6.1, @medusajs/core-flows@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/core-flows@npm:2.6.1" dependencies: json-2-csv: "npm:^5.5.4" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 awilix: ^8.0.1 - checksum: 10c0/702b2960a259e02dc585a37fc5ea5dc6259805befa67e9d5d8204ec84b56e817fdd019ea82b20de8f1cf8c455c49bd223d3b896d4e0b380f3723ac170c0e53d3 + checksum: 10c0/d7a5764d55ed9da7b5e049f4b579eca3ab6c57c21cc1905a40cf146d964177a523009435747bdb8b21e93efd56f86347bc8335351f1df28633ef019eefe99a11 languageName: node linkType: hard @@ -2502,16 +2513,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/currency@npm:^2.5.0, @medusajs/currency@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/currency@npm:2.6.0" +"@medusajs/currency@npm:2.6.1, @medusajs/currency@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/currency@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/0d800dea048e0a8bb00e72bce368a0083b18a041ae5a2b4f5640673832fe39423ecf771ecbbf9f1c4464ce0d5a7b31974eb27e92173d5fe9b21008a2ceedf510 + checksum: 10c0/ad7884fd4615c89cfc46983e5d6efa1fa0889776dfa02664c88a0da7a8eb8b2367e9217f21c9adce14dcf704fd6d0bd4e105768377900daee842482ea3d8184f languageName: node linkType: hard @@ -2528,16 +2539,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/customer@npm:^2.5.0, @medusajs/customer@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/customer@npm:2.6.0" +"@medusajs/customer@npm:2.6.1, @medusajs/customer@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/customer@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/c71aa4c4472158a92af3f0eefa8cc7a4c78625b44f82be262ee0f6ca114cdc495d92eb8cdf4c17013fec701acb468cd192b5df761e8138dc30e8e7e060aeecdf + checksum: 10c0/d9ea80990e8a2b2be664f82f9d5d2d6c91e5e2dbbdf795bf826f4dcb9475c3fe37a2723ed5097f90aef80b69c77d8cc4ceed2900ce73b8b6b42bf0e5498ecd5e languageName: node linkType: hard @@ -2595,19 +2606,19 @@ __metadata: languageName: node linkType: hard -"@medusajs/dashboard@npm:2.6.0": - version: 2.6.0 - resolution: "@medusajs/dashboard@npm:2.6.0" +"@medusajs/dashboard@npm:2.6.1": + version: 2.6.1 + resolution: "@medusajs/dashboard@npm:2.6.1" dependencies: "@ariakit/react": "npm:^0.4.15" "@dnd-kit/core": "npm:^6.1.0" "@dnd-kit/sortable": "npm:^8.0.0" "@hookform/error-message": "npm:^2.0.1" "@hookform/resolvers": "npm:3.4.2" - "@medusajs/admin-shared": "npm:^2.6.0" - "@medusajs/icons": "npm:^2.6.0" - "@medusajs/js-sdk": "npm:^2.6.0" - "@medusajs/ui": "npm:~4.0.6" + "@medusajs/admin-shared": "npm:2.6.1" + "@medusajs/icons": "npm:2.6.1" + "@medusajs/js-sdk": "npm:2.6.1" + "@medusajs/ui": "npm:4.0.7" "@tanstack/react-query": "npm:5.64.2" "@tanstack/react-table": "npm:8.20.5" "@tanstack/react-virtual": "npm:^3.8.3" @@ -2632,18 +2643,18 @@ __metadata: react-jwt: "npm:^1.2.0" react-router-dom: "npm:6.20.1" zod: "npm:3.22.4" - checksum: 10c0/4a4deac59d8a8115f7336dc25a20e44cbb7e6c648945827e8d6b2adfac4144cdffd1b19c542d767820005a7a3e1dfe1b137c86fd33dbb7f03c6fd72959caec7d + checksum: 10c0/1e4b533af93cd4441d435e641adac7a229f12188545d7758a5565dfc0f339ad1ebc2b530d7d5e594cf2a367840624df2156dd91dba986467c69debb8cdc57f3d languageName: node linkType: hard -"@medusajs/event-bus-local@npm:^2.5.0, @medusajs/event-bus-local@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/event-bus-local@npm:2.6.0" +"@medusajs/event-bus-local@npm:2.6.1, @medusajs/event-bus-local@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/event-bus-local@npm:2.6.1" dependencies: ulid: "npm:^2.3.0" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/66c0e5937c1ee48ebd8e2deccfd58942e5242e2afd301c1ad7c92daefcefacf2aabe51261a711293ef199a3c2d6c88d64d96ee6741151b9823b2b50e49a8b0d4 + "@medusajs/framework": 2.6.1 + checksum: 10c0/9f70f81d8797fa35f0776f77f2ce10a7c4c0731514e153022990ef2219cc4c9f34ca54d8baba221703392f374af6f4d7b6e4218d4548ea52f55245356dbc09dc languageName: node linkType: hard @@ -2658,16 +2669,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/event-bus-redis@npm:^2.5.0, @medusajs/event-bus-redis@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/event-bus-redis@npm:2.6.0" +"@medusajs/event-bus-redis@npm:2.6.1, @medusajs/event-bus-redis@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/event-bus-redis@npm:2.6.1" dependencies: bullmq: "npm:5.13.0" ioredis: "npm:^5.4.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 awilix: ^8.0.1 - checksum: 10c0/d1cb9d6e6d69a9506f1a55dee15e96b4dec10dd22561fdaf19f7e9fa1866cba2578d37d3cf38e1ed88f750bb05118c1cd88b644aa6f3350e0ab0cf6191575b09 + checksum: 10c0/c05147ccdabad3e3b33d4bd4e7748de8ad832b88bb7efc7d29cbebdda79b44ef97de099b1941a14954afd4d54d357d75a64530a241262ae69221ccb495baae7f languageName: node linkType: hard @@ -2684,12 +2695,12 @@ __metadata: languageName: node linkType: hard -"@medusajs/file-local@npm:^2.5.0, @medusajs/file-local@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/file-local@npm:2.6.0" +"@medusajs/file-local@npm:2.6.1, @medusajs/file-local@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/file-local@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/70ba24658d177d33e6f2ac0e6f5f62b063ffbce76499cf39b11ca493adcfa7ca4cdbbb8999b43356a8edf153bf27f855f63ee5831643b9a51a87b46964f7de1a + "@medusajs/framework": 2.6.1 + checksum: 10c0/7731abef423ef839e6ee9860752fec061c30cba0e46ecd5774074928d813ed885f3dc9b7636440c8d02e70733ea5e5bf205f81127475c828d9c528de45985a42 languageName: node linkType: hard @@ -2702,16 +2713,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/file-s3@npm:^2.5.0, @medusajs/file-s3@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/file-s3@npm:2.6.0" +"@medusajs/file-s3@npm:2.6.1, @medusajs/file-s3@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/file-s3@npm:2.6.1" dependencies: "@aws-sdk/client-s3": "npm:^3.556.0" "@aws-sdk/s3-request-presigner": "npm:^3.556.0" ulid: "npm:^2.3.0" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/762e2cd1b2753f8b6e2053f34332840885ee899ae08a8f1e015a15d93b2313a91a1521871fbd14e36500a95dead291525d93c17d5637f6e2185c10a32d056d5b + "@medusajs/framework": 2.6.1 + checksum: 10c0/1130dad21114cf3b5982d3f0cc9e8e67c77d3af247763c4a0840b5eeea0e73c4c1e887e39d002e54f1c2b320be5c94da80321b7185e03ba715be7d6fcf1d3386 languageName: node linkType: hard @@ -2728,13 +2739,13 @@ __metadata: languageName: node linkType: hard -"@medusajs/file@npm:^2.5.0, @medusajs/file@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/file@npm:2.6.0" +"@medusajs/file@npm:2.6.1, @medusajs/file@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/file@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 awilix: ^8.0.1 - checksum: 10c0/98c7c3e78c0378a2e5e2dfe3d7e799e3095dc21c76c3eaf363bd7e8c6717d53d63359656b9cdc365986a97494e2eff6003cc9cb78cef95ad6a993fe64a5115d2 + checksum: 10c0/afe383fde591b7b2a074dbb1dbe40a05a524e669ff5283d24b7382f2cb1a705075f7b44f27221e4b2e37d6bfc59bb50697fd85b604ddfbe05c50331e274120ab languageName: node linkType: hard @@ -2848,17 +2859,17 @@ __metadata: languageName: node linkType: hard -"@medusajs/framework@npm:2.6.0": - version: 2.6.0 - resolution: "@medusajs/framework@npm:2.6.0" +"@medusajs/framework@npm:^2.6.1": + version: 2.6.1 + resolution: "@medusajs/framework@npm:2.6.1" dependencies: "@jercle/yargonaut": "npm:^1.1.5" - "@medusajs/modules-sdk": "npm:^2.6.0" - "@medusajs/orchestration": "npm:^2.6.0" - "@medusajs/telemetry": "npm:^2.6.0" - "@medusajs/types": "npm:^2.6.0" - "@medusajs/utils": "npm:^2.6.0" - "@medusajs/workflows-sdk": "npm:^2.6.0" + "@medusajs/modules-sdk": "npm:2.6.1" + "@medusajs/orchestration": "npm:2.6.1" + "@medusajs/telemetry": "npm:2.6.1" + "@medusajs/types": "npm:2.6.1" + "@medusajs/utils": "npm:2.6.1" + "@medusajs/workflows-sdk": "npm:2.6.1" "@opentelemetry/api": "npm:^1.9.0" "@types/express": "npm:^4.17.17" chokidar: "npm:^3.4.2" @@ -2876,7 +2887,7 @@ __metadata: tsconfig-paths: "npm:^4.2.0" zod: "npm:3.22.4" peerDependencies: - "@medusajs/cli": ^2.4.0 + "@medusajs/cli": 2.6.1 "@mikro-orm/cli": 6.4.3 "@mikro-orm/core": 6.4.3 "@mikro-orm/knex": 6.4.3 @@ -2895,16 +2906,16 @@ __metadata: optional: true bin: medusa-mikro-orm: dist/mikro-orm-cli/bin.js - checksum: 10c0/009faa3c8c864e0a5b5b9456487ecf7f20020acefa2e7401bad065e7492c07faa16909e9c557c78bdb17ddb2a87ef67a67b6c7b5aa0ee8062b1b644d3b23e3b9 + checksum: 10c0/091e262cc368be3c191e9742d0cc29bae7383e780a0b75d11e69eede778d799896e26184468175933a6d827a5b3a7246e57ad160efee0c2322261e7994a5616c languageName: node linkType: hard -"@medusajs/fulfillment-manual@npm:^2.5.0, @medusajs/fulfillment-manual@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/fulfillment-manual@npm:2.6.0" +"@medusajs/fulfillment-manual@npm:2.6.1, @medusajs/fulfillment-manual@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/fulfillment-manual@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/d81df45085e0d7f6e0f3b4bdcdde18038c82e18807484cbfa3b27c36e766a50690b5f0aabe0b9bcfe98357904d531097e13bcb46ce658b53c96ef2cffbf54ea4 + "@medusajs/framework": 2.6.1 + checksum: 10c0/d381faa5546f0eec68eb9cf8526ff086b96b2abc9abe34b4b63a76750c9a946d60192168c8487381b6897198d707e638e5b6a8c3d87a66832344e1d02a02d0b4 languageName: node linkType: hard @@ -2917,16 +2928,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/fulfillment@npm:^2.5.0, @medusajs/fulfillment@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/fulfillment@npm:2.6.0" +"@medusajs/fulfillment@npm:2.6.1, @medusajs/fulfillment@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/fulfillment@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/9374b2edfea393500075651bcad67846396b1e4814797b94885672d9ce3b72530ae56aefbaf79fc61c6c112643679c920ae5baa1113df2f0c396f874c2ced731 + checksum: 10c0/a00d2fd0e40beb84ee06945fc44d3f00767b75aeca63587e99ff5fb3c35edb31e1fbbfea6ba5ff72088bf57a4929e6b4ef8841fec485cb0a76a9f4968e78f779 languageName: node linkType: hard @@ -2961,35 +2972,26 @@ __metadata: languageName: node linkType: hard -"@medusajs/icons@npm:2.6.0, @medusajs/icons@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/icons@npm:2.6.0" - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - checksum: 10c0/cb8628018398aba010bb7b1f653cb7dc91d9bd59a40f1e7ee4cdc7732559e75062db790fb609fd3f748a9b80ccc0f421267a414ed9f5a7a4e079ef643e65333e - languageName: node - linkType: hard - -"@medusajs/icons@npm:^2.5.1": - version: 2.5.1 - resolution: "@medusajs/icons@npm:2.5.1" +"@medusajs/icons@npm:2.6.1, @medusajs/icons@npm:^2.6.1": + version: 2.6.1 + resolution: "@medusajs/icons@npm:2.6.1" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - checksum: 10c0/f7fbe17475d8c39bd584103ec662f90aa5c8f07159f5820648eba8a0adf42a0d48057518da5a22503e5d5eaca552cbb7b26792613e2ec84827be1bbbafb64201 + checksum: 10c0/368e3101596244396d925ab4553eecd444804f20bc2e65f80ad138ddf91844eebf44671bee171af3e17ae3e4eb2aa6ef3c7c29c690e1eb61a1ba4f13e3021338 languageName: node linkType: hard -"@medusajs/index@npm:^2.5.0, @medusajs/index@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/index@npm:2.6.0" +"@medusajs/index@npm:2.6.1, @medusajs/index@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/index@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/knex": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/0988f02b8666bc04c093d3fee78c4430ccfd5eeb73955735b55909042d7d71f6a012547ace9ade4b66ee3140a31142464a3159cab3b3c90512f8a15479fcec6b + checksum: 10c0/8f930babcdf0c14eea3777d891e70f8ab178e6f5480ed783faa383f9b6e9cdd84ce5566237b0a744335d79277a2ac469081c2d1c505fa8131ed48ac071dd50f2 languageName: node linkType: hard @@ -3007,16 +3009,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/inventory@npm:^2.5.0, @medusajs/inventory@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/inventory@npm:2.6.0" +"@medusajs/inventory@npm:2.6.1, @medusajs/inventory@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/inventory@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/c821d835f60e1c73f06c6e77d97e45ef53d2a6a8cd5e71cec7e5e0be94ec84eacf5469640389885c66dd34ef03982db057353994a02e4bf0969d8a8c65607622 + checksum: 10c0/d455335ab3fa76c97a36043127d7b853e630859832903c778fe527b127ef4a92b681d2e12e1b235b3f6a10f0bda2444007abfe4ccba8e80a3eb9a62c348c3f69 languageName: node linkType: hard @@ -3044,14 +3046,14 @@ __metadata: languageName: node linkType: hard -"@medusajs/js-sdk@npm:2.6.0, @medusajs/js-sdk@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/js-sdk@npm:2.6.0" +"@medusajs/js-sdk@npm:2.6.1, @medusajs/js-sdk@npm:^2.6.1": + version: 2.6.1 + resolution: "@medusajs/js-sdk@npm:2.6.1" dependencies: - "@medusajs/types": "npm:^2.6.0" + "@medusajs/types": "npm:2.6.1" fetch-event-stream: "npm:^0.1.5" qs: "npm:^6.12.1" - checksum: 10c0/7f7314e0674badedcf7f16cbfb873abd9ebc41bd720c2ea8b7cde1e0c1a37e5c9b8d0229c63691a44fe1f6c555f8cb6cdb97e81f51191e64a6df448d390c860f + checksum: 10c0/afa2ec90b64c4e12d2723237f5880da9d05a5ae78b59590b9be01805c5657d8ad7a1c0ea63519e1f25c3c8f8cfb5d2140b33846b797621eb99007e0364be6636 languageName: node linkType: hard @@ -3066,16 +3068,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/link-modules@npm:^2.5.0, @medusajs/link-modules@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/link-modules@npm:2.6.0" +"@medusajs/link-modules@npm:2.6.1, @medusajs/link-modules@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/link-modules@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/c0acfafd2213bf97b77cf02305c76f47123c4528ff56591aec001f4aa4ca3b6bf80f4f6b94793124d3f5c43e7598b325a376456572b4483db7bdaaf917ecf52a + checksum: 10c0/aadeefea1ab3133f92510d0477478a67cdb6c602d3634af9e0517f39ddc11c18645ede89c34a1bb6a503fd3e7395efbb3288c9d64a2510b283f1326efadd9934 languageName: node linkType: hard @@ -3092,12 +3094,12 @@ __metadata: languageName: node linkType: hard -"@medusajs/locking-postgres@npm:^2.5.0, @medusajs/locking-postgres@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/locking-postgres@npm:2.6.0" +"@medusajs/locking-postgres@npm:2.6.1, @medusajs/locking-postgres@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/locking-postgres@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/eaea765eed4997b57aed900865d863a031a40b79929eb60506f0e7440460b63e2a4e051325f66e8c3531be5ae1b0a63d249bcac980cdeb4fae6830c61a033d25 + "@medusajs/framework": 2.6.1 + checksum: 10c0/f21a984c155114ae52e46077a1af9efa263ad7766967bbf614ad43f5612f95f40112567aa655269b0a2e04c072ec9fca5cc0c515bed15b4f4194bc5c2026e093 languageName: node linkType: hard @@ -3110,14 +3112,14 @@ __metadata: languageName: node linkType: hard -"@medusajs/locking-redis@npm:^2.5.0, @medusajs/locking-redis@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/locking-redis@npm:2.6.0" +"@medusajs/locking-redis@npm:2.6.1, @medusajs/locking-redis@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/locking-redis@npm:2.6.1" dependencies: ioredis: "npm:^5.4.1" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/fcefc4b1fdfac3ab38bce90abaf8a715b4eeb5a44abc8712eded8bad908bd54f799f773f28a53708a268d9be003522edce49778fe4f7e53c16c49c34c16f0337 + "@medusajs/framework": 2.6.1 + checksum: 10c0/48f37d56f39117914b4f303a853a2a82f6a4573b4bc224cf3463557aa39ea3c13c481716cf5c4ce1b0b19a18e53e7e24acdea68d209fd13dd5f9e899b1350d41 languageName: node linkType: hard @@ -3132,16 +3134,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/locking@npm:^2.5.0, @medusajs/locking@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/locking@npm:2.6.0" +"@medusajs/locking@npm:2.6.1, @medusajs/locking@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/locking@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/6d6043bf36f40f33e340af709b7ff643abaad592e196c8259059cfa862273be6453c6c37bdc153377bdee5f6e4d789dd7e6813678cecf7712a5bc9b98541b2c2 + checksum: 10c0/7368d54856aa391f257871ad46555b2e7efc907dde0af57693f54b730cc7dbe79219a99952be13428e698b9c86cc51a28d6ac2e70ff7e659d35e9f947bf57553 languageName: node linkType: hard @@ -3325,55 +3327,55 @@ __metadata: languageName: node linkType: hard -"@medusajs/medusa@npm:2.6.0": - version: 2.6.0 - resolution: "@medusajs/medusa@npm:2.6.0" +"@medusajs/medusa@npm:^2.6.1": + version: 2.6.1 + resolution: "@medusajs/medusa@npm:2.6.1" dependencies: "@inquirer/checkbox": "npm:^2.3.11" "@inquirer/input": "npm:^2.2.9" - "@medusajs/admin-bundler": "npm:^2.6.0" - "@medusajs/api-key": "npm:^2.6.0" - "@medusajs/auth": "npm:^2.6.0" - "@medusajs/auth-emailpass": "npm:^2.6.0" - "@medusajs/auth-github": "npm:^2.6.0" - "@medusajs/auth-google": "npm:^2.6.0" - "@medusajs/cache-inmemory": "npm:^2.6.0" - "@medusajs/cache-redis": "npm:^2.6.0" - "@medusajs/cart": "npm:^2.6.0" - "@medusajs/core-flows": "npm:^2.6.0" - "@medusajs/currency": "npm:^2.6.0" - "@medusajs/customer": "npm:^2.6.0" - "@medusajs/event-bus-local": "npm:^2.6.0" - "@medusajs/event-bus-redis": "npm:^2.6.0" - "@medusajs/file": "npm:^2.6.0" - "@medusajs/file-local": "npm:^2.6.0" - "@medusajs/file-s3": "npm:^2.6.0" - "@medusajs/fulfillment": "npm:^2.6.0" - "@medusajs/fulfillment-manual": "npm:^2.6.0" - "@medusajs/index": "npm:^2.6.0" - "@medusajs/inventory": "npm:^2.6.0" - "@medusajs/link-modules": "npm:^2.6.0" - "@medusajs/locking": "npm:^2.6.0" - "@medusajs/locking-postgres": "npm:^2.6.0" - "@medusajs/locking-redis": "npm:^2.6.0" - "@medusajs/notification": "npm:^2.6.0" - "@medusajs/notification-local": "npm:^2.6.0" - "@medusajs/notification-sendgrid": "npm:^2.6.0" - "@medusajs/order": "npm:^2.6.0" - "@medusajs/payment": "npm:^2.6.0" - "@medusajs/payment-stripe": "npm:^2.6.0" - "@medusajs/pricing": "npm:^2.6.0" - "@medusajs/product": "npm:^2.6.0" - "@medusajs/promotion": "npm:^2.6.0" - "@medusajs/region": "npm:^2.6.0" - "@medusajs/sales-channel": "npm:^2.6.0" - "@medusajs/stock-location": "npm:^2.6.0" - "@medusajs/store": "npm:^2.6.0" - "@medusajs/tax": "npm:^2.6.0" - "@medusajs/telemetry": "npm:^2.6.0" - "@medusajs/user": "npm:^2.6.0" - "@medusajs/workflow-engine-inmemory": "npm:^2.6.0" - "@medusajs/workflow-engine-redis": "npm:^2.6.0" + "@medusajs/admin-bundler": "npm:2.6.1" + "@medusajs/api-key": "npm:2.6.1" + "@medusajs/auth": "npm:2.6.1" + "@medusajs/auth-emailpass": "npm:2.6.1" + "@medusajs/auth-github": "npm:2.6.1" + "@medusajs/auth-google": "npm:2.6.1" + "@medusajs/cache-inmemory": "npm:2.6.1" + "@medusajs/cache-redis": "npm:2.6.1" + "@medusajs/cart": "npm:2.6.1" + "@medusajs/core-flows": "npm:2.6.1" + "@medusajs/currency": "npm:2.6.1" + "@medusajs/customer": "npm:2.6.1" + "@medusajs/event-bus-local": "npm:2.6.1" + "@medusajs/event-bus-redis": "npm:2.6.1" + "@medusajs/file": "npm:2.6.1" + "@medusajs/file-local": "npm:2.6.1" + "@medusajs/file-s3": "npm:2.6.1" + "@medusajs/fulfillment": "npm:2.6.1" + "@medusajs/fulfillment-manual": "npm:2.6.1" + "@medusajs/index": "npm:2.6.1" + "@medusajs/inventory": "npm:2.6.1" + "@medusajs/link-modules": "npm:2.6.1" + "@medusajs/locking": "npm:2.6.1" + "@medusajs/locking-postgres": "npm:2.6.1" + "@medusajs/locking-redis": "npm:2.6.1" + "@medusajs/notification": "npm:2.6.1" + "@medusajs/notification-local": "npm:2.6.1" + "@medusajs/notification-sendgrid": "npm:2.6.1" + "@medusajs/order": "npm:2.6.1" + "@medusajs/payment": "npm:2.6.1" + "@medusajs/payment-stripe": "npm:2.6.1" + "@medusajs/pricing": "npm:2.6.1" + "@medusajs/product": "npm:2.6.1" + "@medusajs/promotion": "npm:2.6.1" + "@medusajs/region": "npm:2.6.1" + "@medusajs/sales-channel": "npm:2.6.1" + "@medusajs/stock-location": "npm:2.6.1" + "@medusajs/store": "npm:2.6.1" + "@medusajs/tax": "npm:2.6.1" + "@medusajs/telemetry": "npm:2.6.1" + "@medusajs/user": "npm:2.6.1" + "@medusajs/workflow-engine-inmemory": "npm:2.6.1" + "@medusajs/workflow-engine-redis": "npm:2.6.1" boxen: "npm:^5.0.1" chalk: "npm:^4.0.0" chokidar: "npm:^3.4.2" @@ -3390,12 +3392,12 @@ __metadata: uuid: "npm:^9.0.0" zod: "npm:3.22.4" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/knex": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 - "@swc/core": ^1.7.28 + "@swc/core": 1.5.7 awilix: ^8.0.1 react-dom: ^18.0.0 yalc: 1.0.0-pre.53 @@ -3406,17 +3408,17 @@ __metadata: optional: true yalc: optional: true - checksum: 10c0/7b95ba26ced705b62cd0f14164594f64db78d024516b8ba53a70b7d356853402e1ed739e1fba38d610b61f5dfa96d251af3ea60f03ee0aadbc8a2ff313958335 + checksum: 10c0/d8095824c23b924ee68e53e22d17ea24dcb9917031c61f5a5f07db482e897bc1d837fa783ae331f47853b225b4f44ae145502992d2c3a0acf6b2bcf054155fb4 languageName: node linkType: hard -"@medusajs/modules-sdk@npm:^2.5.0, @medusajs/modules-sdk@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/modules-sdk@npm:2.6.0" +"@medusajs/modules-sdk@npm:2.6.1, @medusajs/modules-sdk@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/modules-sdk@npm:2.6.1" dependencies: - "@medusajs/orchestration": "npm:^2.6.0" - "@medusajs/types": "npm:^2.6.0" - "@medusajs/utils": "npm:^2.6.0" + "@medusajs/orchestration": "npm:2.6.1" + "@medusajs/types": "npm:2.6.1" + "@medusajs/utils": "npm:2.6.1" peerDependencies: "@mikro-orm/core": 6.4.3 "@mikro-orm/knex": 6.4.3 @@ -3425,7 +3427,7 @@ __metadata: awilix: ^8.0.1 express: ^4.21.0 pg: ^8.13.0 - checksum: 10c0/fb7211101ccfbd8e60db0e66a345bff7e11836efd173a164f3310e4ab2e0363c6f7b2200da8a52b2fedefd3ab1bc8ea896e9dae169732df6123343b40860308c + checksum: 10c0/9f7831ff3fc0069ead6ed73ec97ee44f36966865a46a6a38202a1846b55b60faceb1770e3761a4df6e6f15c0c5210ce2859700a0555a0921e12688659d6b92cc languageName: node linkType: hard @@ -3448,12 +3450,12 @@ __metadata: languageName: node linkType: hard -"@medusajs/notification-local@npm:^2.5.0, @medusajs/notification-local@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/notification-local@npm:2.6.0" +"@medusajs/notification-local@npm:2.6.1, @medusajs/notification-local@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/notification-local@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/870aa3c9b99368f2b0b28a1ccbb040990499aa82a473d9adc2227bf56f71d73907d1ef401bc82daf21724d3c64b95fcd1c8c798c3c437756a9bda2550e3f4db8 + "@medusajs/framework": 2.6.1 + checksum: 10c0/d596b66d92b4c6bc0d50bf9699c14d8d08cd991ffce78b48c8c85c2e3a72e573ec21520227c401a7447840a3819b387ba8f8f44009b270913686ff10d992da95 languageName: node linkType: hard @@ -3466,14 +3468,14 @@ __metadata: languageName: node linkType: hard -"@medusajs/notification-sendgrid@npm:^2.5.0, @medusajs/notification-sendgrid@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/notification-sendgrid@npm:2.6.0" +"@medusajs/notification-sendgrid@npm:2.6.1, @medusajs/notification-sendgrid@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/notification-sendgrid@npm:2.6.1" dependencies: "@sendgrid/mail": "npm:^8.1.3" peerDependencies: - "@medusajs/framework": ^2.4.0 - checksum: 10c0/4ebf3b20f75642b18f3ea79e377b2840708d3962a890e1fadee6c0149bb9d89d1303f167c9f31ee7ff96e17f80f2543f43bb6194dd61b1e013d0f916d205ef1e + "@medusajs/framework": 2.6.1 + checksum: 10c0/af631416e5cbe2edfe8b8f7b64521b272770e39330101b9625b25fa0ed8ed105565d14fa16491c8f4eaece376cc11f717f87111fb0fbd127994fe2b7162f4933 languageName: node linkType: hard @@ -3488,16 +3490,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/notification@npm:^2.5.0, @medusajs/notification@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/notification@npm:2.6.0" +"@medusajs/notification@npm:2.6.1, @medusajs/notification@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/notification@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/b0680928f18a3f793eb97b1a7b132bd89c6754b9279df349c404db1b4ee80be5f3a207a94bc65f9c82865d27aa0f458645810ec1a61c23df19be7c0761e2004b + checksum: 10c0/c7e7402ad06a3af423e8ba9a39d7071daa5662cced67f4ee3e1721f883c7c52fc84fc428d3f4aac6daad9751294f91f17998b4985223c3b84f4e0b3579184eba languageName: node linkType: hard @@ -3514,12 +3516,12 @@ __metadata: languageName: node linkType: hard -"@medusajs/orchestration@npm:^2.5.0, @medusajs/orchestration@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/orchestration@npm:2.6.0" +"@medusajs/orchestration@npm:2.6.1, @medusajs/orchestration@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/orchestration@npm:2.6.1" dependencies: - "@medusajs/types": "npm:^2.6.0" - "@medusajs/utils": "npm:^2.6.0" + "@medusajs/types": "npm:2.6.1" + "@medusajs/utils": "npm:2.6.1" peerDependencies: "@mikro-orm/core": 6.4.3 "@mikro-orm/knex": 6.4.3 @@ -3528,7 +3530,7 @@ __metadata: awilix: ^8.0.1 express: ^4.21.0 pg: ^8.13.0 - checksum: 10c0/e0bbfea2ee9cde91c9c7eb9143d263b4048b93c7cd99d06071bcabbf7ed53a2c0bf7528e64ef23e68b1dea1f6849ee823c76608166110d8517eb5e174f3c07b7 + checksum: 10c0/7d79e20e757dc7589b906cecb8e6a2abf494f3295f249280f99728e56cdbd98e21317beb7621016f0d94b12c38dcce579ada1476f99f5f6b7c2034ba2b2a8e9f languageName: node linkType: hard @@ -3550,16 +3552,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/order@npm:^2.5.0, @medusajs/order@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/order@npm:2.6.0" +"@medusajs/order@npm:2.6.1, @medusajs/order@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/order@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/efd70574256fe2789853c1f05d66e515cbe4fb2e2f569dfd0b35802fecf4e3dfc1be62069b4e4361af428a5f918b7bd157e28892a4cc04d26f05ae6e8e351449 + checksum: 10c0/d97c9c160f6146ab927a7c9318f22b3ae53ef8d6ec71144c17c629cad0b9de017d3fcd2307a33be2b44c8fc7d390d30a973ade38b47fb19116b679be470d13e6 languageName: node linkType: hard @@ -3576,15 +3578,15 @@ __metadata: languageName: node linkType: hard -"@medusajs/payment-stripe@npm:^2.5.0, @medusajs/payment-stripe@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/payment-stripe@npm:2.6.0" +"@medusajs/payment-stripe@npm:2.6.1, @medusajs/payment-stripe@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/payment-stripe@npm:2.6.1" dependencies: stripe: "npm:^15.5.0" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 awilix: ^8.0.1 - checksum: 10c0/dce62df1ecdaa796dfe1d28b52fb5939a06ea2a4109bce70d487e5f04e27e96b7a0f8c843dd381fed560a2bc5cf8236ca710c2c471cbe8a7df1030558fbbc5ff + checksum: 10c0/d87a73c848286ec546a34be5abec63b689ae278e5411805c69874ed6dd116335e317c0e2dbd696b9e7019bf74f688c629af2ad6fb83aa56544d9a2e1d76886c4 languageName: node linkType: hard @@ -3600,16 +3602,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/payment@npm:^2.5.0, @medusajs/payment@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/payment@npm:2.6.0" +"@medusajs/payment@npm:2.6.1, @medusajs/payment@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/payment@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/79556d60796c3f7329fc23cbc2c329daa6a0e8ba3bf3674e587ef9929b8bcb616a7886b731bb42e62c5f0992cf80985f5bacde4975b70550cd4e021f7fded292 + checksum: 10c0/24b23c9719458e20589e55a8c74e2d566592bc63cb2184501f6290d81b0b417f43520817f689618c60d99328cc6f2a6fdcbc49c670064a08d1491309f4c9228c languageName: node linkType: hard @@ -3626,16 +3628,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/pricing@npm:^2.5.0, @medusajs/pricing@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/pricing@npm:2.6.0" +"@medusajs/pricing@npm:2.6.1, @medusajs/pricing@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/pricing@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/0ceabcea4b96c1da33c151fbefde9fb2e9eae5532bd69a7f8cfce5a01df9e2432b77f5825e5038200552e022c0e3cb9298d00af7c79b045e55e565966826e240 + checksum: 10c0/0c10daf3f225aa562e54c7f31b34c5e253b0359717a6e84a5d88d0cf4f0c69c0685dc5faa85d62e0db3271ff81871c0e2e35fc90a4e2b4c1f0c5b2dc15b0a56d languageName: node linkType: hard @@ -3652,16 +3654,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/product@npm:^2.5.0, @medusajs/product@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/product@npm:2.6.0" +"@medusajs/product@npm:2.6.1, @medusajs/product@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/product@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/bd55f37fde198f941750023b7fbd161cbf9983d8bf80dc5c61066446189fe7ea7a44fa30b503212b6f6b567b38045e2239b22486c36171d1cbd27945d289475c + checksum: 10c0/fc866831654c540678f0190055a8f427c9e8ffceeb997fbf865dbf46f1f986937d3e7730f74328c937a86b556e25471a4fecc43d1801377a08f9bf6b87c1e05b languageName: node linkType: hard @@ -3678,16 +3680,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/promotion@npm:^2.5.0, @medusajs/promotion@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/promotion@npm:2.6.0" +"@medusajs/promotion@npm:2.6.1, @medusajs/promotion@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/promotion@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/faf8b3578391816300cabbeebec353aa304e72e65f1eaf82043c9dbab35a83371c43cb5e9728e000f1089147ed05860f2c3840daf9420e440406972699bc4258 + checksum: 10c0/7035184c6de8b06300955d00afc1f1c6afca2e7fd3bb84ed137219251834a226b25427eb6d1ee392506d92202da31324701e75b3dbf679602a6991ac9605dbfa languageName: node linkType: hard @@ -3704,16 +3706,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/region@npm:^2.5.0, @medusajs/region@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/region@npm:2.6.0" +"@medusajs/region@npm:2.6.1, @medusajs/region@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/region@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/8213e6a66bc1af847059a9ad638c30159f0fbd5c15ebc9382aeec4dc4b201aacfc129cc5b102d3d51298b877d56338824bd58727829994a7b9af923f338c02c5 + checksum: 10c0/91ae83a75d2d6a7eb57ee0c4ca0c2b045313af710f9e91b56d4c9a066e360e50a75b10bcf75e4fc1ab5646172734a54a1e70a762353b7ba6e28fb74ae2922b17 languageName: node linkType: hard @@ -3730,16 +3732,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/sales-channel@npm:^2.5.0, @medusajs/sales-channel@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/sales-channel@npm:2.6.0" +"@medusajs/sales-channel@npm:2.6.1, @medusajs/sales-channel@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/sales-channel@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/72ac301c5427c94cdb99d7a1df80bb45834e71ae4dfe39b25b1159c8134aee199853c374be621eb61b8fb299765ca3438e7f6db7540d62c30ab6b73e4df6d83a + checksum: 10c0/54e2438ab7c27acf40da994fe35291b956427fe5ce76bbc818ca2fe0b3920aa8ebba321c7722413572283cee833698389d02e506e6841203a9d68e6fcb9a7fc8 languageName: node linkType: hard @@ -3756,16 +3758,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/stock-location@npm:^2.5.0, @medusajs/stock-location@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/stock-location@npm:2.6.0" +"@medusajs/stock-location@npm:2.6.1, @medusajs/stock-location@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/stock-location@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/1467cc07eb001e05b1983bb97e0455c9072ec6ac144568912c6553bd92efc4f0bf6be795f07d05ae32344960225aa2fc92e0a4106e25c4dbb6edddfca204a395 + checksum: 10c0/af6923d032d749da33d993e974f3d74068e261a98d33e09c9e11456cfa6789ef9b1fe10494cfcd82c72846954d8aa20850b9fcde0ddabd5af3221e3b79091e52 languageName: node linkType: hard @@ -3782,16 +3784,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/store@npm:^2.5.0, @medusajs/store@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/store@npm:2.6.0" +"@medusajs/store@npm:2.6.1, @medusajs/store@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/store@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/8da3a3bad9dd79aafe5814e12ecbcdaf3229e769e4c65a13a43d2ccee06c3a57e8121b222087ad5b92e01aeaffc90cd015439e16a0eaac26a9957e56c012c425 + checksum: 10c0/e2b3f1ad9475ccddb013e634bdc2a944f45413943079e782fe03674c28a173098ebf6fc2e5738983569e9208f6127d9f0f1b05aa10e753648cc98742258816bc languageName: node linkType: hard @@ -3808,16 +3810,16 @@ __metadata: languageName: node linkType: hard -"@medusajs/tax@npm:^2.5.0, @medusajs/tax@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/tax@npm:2.6.0" +"@medusajs/tax@npm:2.6.1, @medusajs/tax@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/tax@npm:2.6.1" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/6974db06574ffa55bb44401dd1db7a346c2b4c04b4dd69fa8e36df1bb718f908e2f5c2d357fc6cd3935a338ba39519955cfe1487100958faab4e320b950aee88 + checksum: 10c0/631d921d76ff3b9fa7e8cf4f224defffdd9f4b0c3434a2f83e63aac7072c495c58cc382331c1fff8edfebe66d34578acaba37b04e40cb48842cc4d9249cad7ff languageName: node linkType: hard @@ -3834,9 +3836,9 @@ __metadata: languageName: node linkType: hard -"@medusajs/telemetry@npm:^2.5.0, @medusajs/telemetry@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/telemetry@npm:2.6.0" +"@medusajs/telemetry@npm:2.6.1, @medusajs/telemetry@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/telemetry@npm:2.6.1" dependencies: "@babel/runtime": "npm:^7.22.10" axios: "npm:^0.21.4" @@ -3848,7 +3850,7 @@ __metadata: is-docker: "npm:^2.2.1" remove-trailing-slash: "npm:^0.1.1" uuid: "npm:^8.3.2" - checksum: 10c0/005dd71ecf2f8391c0f522670fc9f355d045395ab2ebba47885424b07a57e0f7073499cc4909add35437a1b7b9c79087eccb43fe5f8089a4d290836501919674 + checksum: 10c0/37448e2bd9214ca1005929a9738bbaa96a672d5d8db2b4d3aaa602e7dadf89f45fe7fa74ddd37729838f8c9b829099c8f865f1fdd2d5dba0b6db0d9ba4f8a27a languageName: node linkType: hard @@ -3912,9 +3914,9 @@ __metadata: languageName: node linkType: hard -"@medusajs/test-utils@npm:2.6.0": - version: 2.6.0 - resolution: "@medusajs/test-utils@npm:2.6.0" +"@medusajs/test-utils@npm:^2.6.1": + version: 2.6.1 + resolution: "@medusajs/test-utils@npm:2.6.1" dependencies: "@types/express": "npm:^4.17.17" axios: "npm:^0.21.4" @@ -3922,50 +3924,50 @@ __metadata: get-port: "npm:^5.1.0" randomatic: "npm:^3.1.1" peerDependencies: - "@medusajs/framework": ^2.4.0 - "@medusajs/medusa": ^2.4.0 + "@medusajs/framework": 2.6.1 + "@medusajs/medusa": 2.6.1 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 peerDependenciesMeta: "@medusajs/medusa": optional: true - checksum: 10c0/2909074822c4826843c7f6dfa4e37e825959243637d86aa915c75a52420e15c3e180128a8dbd45b366d3e2b095a95574373e728ce5cf94241e80c8a75f64eb36 + checksum: 10c0/bf8454d9389fbc354af084248e95b044e571bdfaf04588aed4c3f679e3596fef9123a3cb3c3e9e6979f5809400e0c0f9081c91cea10073dc2070051b1480c77f languageName: node linkType: hard -"@medusajs/types@npm:^2.5.0": - version: 2.5.0 - resolution: "@medusajs/types@npm:2.5.0" +"@medusajs/types@npm:2.6.1, @medusajs/types@npm:^2.6.1": + version: 2.6.1 + resolution: "@medusajs/types@npm:2.6.1" dependencies: bignumber.js: "npm:^9.1.2" peerDependencies: awilix: ^8.0.1 ioredis: ^5.4.1 - vite: ^5.2.11 + vite: ^5 || ^6 peerDependenciesMeta: ioredis: optional: true vite: optional: true - checksum: 10c0/0f37fb37bbb216f98aaf6af1abea0bd7ee41754bd89859eba4b00c119dd3fd3b5c9691dacf68ea4cfea1ef3803eaa72445d1bb19d5609ab82fd0c481ec296ba4 + checksum: 10c0/356819ba354cc3538779848601c6d09d7c3c171c5516098a060c63256dc28b55e23f48a4afa6c64fc61fcd6b2d6e8f8d4307e86990665b978bcb1fa16d7ea3d3 languageName: node linkType: hard -"@medusajs/types@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/types@npm:2.6.0" +"@medusajs/types@npm:^2.5.0": + version: 2.5.0 + resolution: "@medusajs/types@npm:2.5.0" dependencies: bignumber.js: "npm:^9.1.2" peerDependencies: awilix: ^8.0.1 ioredis: ^5.4.1 - vite: ^5 || ^6 + vite: ^5.2.11 peerDependenciesMeta: ioredis: optional: true vite: optional: true - checksum: 10c0/d405ceb3dfe8647af3d4b51c6c98534eccc13867bff8d1baa8984036391beb1359fb07b67df7e05f7894f07a9581dc3944d794077c03b14e6be4a0e15c106aef + checksum: 10c0/0f37fb37bbb216f98aaf6af1abea0bd7ee41754bd89859eba4b00c119dd3fd3b5c9691dacf68ea4cfea1ef3803eaa72445d1bb19d5609ab82fd0c481ec296ba4 languageName: node linkType: hard @@ -4025,11 +4027,11 @@ __metadata: languageName: node linkType: hard -"@medusajs/ui@npm:^4.0.6, @medusajs/ui@npm:~4.0.6": - version: 4.0.6 - resolution: "@medusajs/ui@npm:4.0.6" +"@medusajs/ui@npm:4.0.7, @medusajs/ui@npm:^4.0.6, @medusajs/ui@npm:^4.0.7": + version: 4.0.7 + resolution: "@medusajs/ui@npm:4.0.7" dependencies: - "@medusajs/icons": "npm:^2.5.1" + "@medusajs/icons": "npm:2.6.1" "@tanstack/react-table": "npm:8.20.5" clsx: "npm:^1.2.1" copy-to-clipboard: "npm:^3.3.3" @@ -4045,22 +4047,22 @@ __metadata: peerDependencies: react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc - checksum: 10c0/ff45b909b3573fd6b443eee0aac47a2f13dbd145ed161e0485f7e22e1e963345e2e38dba236d1b927715feaa79d3dc79671bdeb2075c6f83682dcf8827e6f962 + checksum: 10c0/c320d7b610a50ca7483584cc84865ea7120cb74588173c747ad3ee27aefe575eddf3db2a1d558e791b66ffadc962c8fdfe39fe9fdc71f162e88e057bad480117 languageName: node linkType: hard -"@medusajs/user@npm:^2.5.0, @medusajs/user@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/user@npm:2.6.0" +"@medusajs/user@npm:2.6.1, @medusajs/user@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/user@npm:2.6.1" dependencies: jsonwebtoken: "npm:^9.0.2" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/469dffb85ae9ba2b89364c53d723030b2935500fb86f19814c3f1b332b1e25dd61bb2b552c0b4df1e5543fd1b1585711e1c72bb16906040ec4796cdc31239356 + checksum: 10c0/8bf924caec453ccc7c99554465319259b07dd1ca656790740581f655b2c9bdc2e99095f5dc4bc2654110ff275c95db565bfc908b2a0f2037ec96d8e9e6258b40 languageName: node linkType: hard @@ -4139,15 +4141,15 @@ __metadata: languageName: node linkType: hard -"@medusajs/utils@npm:2.6.0, @medusajs/utils@npm:^2.5.0, @medusajs/utils@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/utils@npm:2.6.0" +"@medusajs/utils@npm:2.6.1, @medusajs/utils@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/utils@npm:2.6.1" dependencies: "@graphql-codegen/core": "npm:^4.0.2" "@graphql-codegen/typescript": "npm:^4.0.9" "@graphql-tools/merge": "npm:^9.0.7" "@graphql-tools/schema": "npm:^10.0.6" - "@medusajs/types": "npm:^2.6.0" + "@medusajs/types": "npm:2.6.1" "@types/pluralize": "npm:^0.0.33" bignumber.js: "npm:^9.1.2" dotenv: "npm:^16.4.5" @@ -4165,23 +4167,23 @@ __metadata: awilix: ^8.0.1 express: ^4.21.0 pg: ^8.13.0 - checksum: 10c0/86321649d20038c8921cc462f16af70539a1bb2979a801f1f66a71c44f5d35b68f8add272d9bd66c78ad2ae9958371cad7e2440755d6da46b1b884a5b9d89419 + checksum: 10c0/d423a396a3a1a821e94853a0afad9e6662c66542aa41a6021dae20f0c5bb3e53f2c68252e13d970b6da3d00589cf483f6146ee52662fecc888e0dd1a8b71f2a2 languageName: node linkType: hard -"@medusajs/workflow-engine-inmemory@npm:^2.5.0, @medusajs/workflow-engine-inmemory@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/workflow-engine-inmemory@npm:2.6.0" +"@medusajs/workflow-engine-inmemory@npm:2.6.1, @medusajs/workflow-engine-inmemory@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/workflow-engine-inmemory@npm:2.6.1" dependencies: cron-parser: "npm:^4.9.0" ulid: "npm:^2.3.0" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/6efc09304828dc525a7db9ca6a4bd9dc4bc537c585d16171d5a211f7866c744ef7fa9e050175317557764731c14690f525a2fc90e227f180cc1357677ad259fd + checksum: 10c0/011029f9f2e78eda39befd3907f25a098296a7bad7510a8cf75aac268642556d35d8daf12b5e15933b0df4aa1414b2e648da9a380bef95a9f1f9d86fb0fab749 languageName: node linkType: hard @@ -4201,20 +4203,20 @@ __metadata: languageName: node linkType: hard -"@medusajs/workflow-engine-redis@npm:^2.5.0, @medusajs/workflow-engine-redis@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/workflow-engine-redis@npm:2.6.0" +"@medusajs/workflow-engine-redis@npm:2.6.1, @medusajs/workflow-engine-redis@npm:^2.5.0": + version: 2.6.1 + resolution: "@medusajs/workflow-engine-redis@npm:2.6.1" dependencies: bullmq: "npm:5.13.0" ioredis: "npm:^5.4.1" ulid: "npm:^2.3.0" peerDependencies: - "@medusajs/framework": ^2.4.0 + "@medusajs/framework": 2.6.1 "@mikro-orm/core": 6.4.3 "@mikro-orm/migrations": 6.4.3 "@mikro-orm/postgresql": 6.4.3 awilix: ^8.0.1 - checksum: 10c0/644c731081844bdcdc13cbbc7de34147d76f5bbf6ad7bad403d6a2a76bcc977a5a96a7a435728bdfbc02d900556dc8f4437eaa8620f0862e258bfbd0f571ef5a + checksum: 10c0/79be56cd50d7a3c2e6934f35a3f31cf244d4d126f8994354f29ec509a4b5a65fb607b929de8cd03d1e0f7c0a264f3441ed5b333d5ff51fa848e8b0c12ac2effe languageName: node linkType: hard @@ -4235,14 +4237,14 @@ __metadata: languageName: node linkType: hard -"@medusajs/workflows-sdk@npm:2.6.0, @medusajs/workflows-sdk@npm:^2.5.0, @medusajs/workflows-sdk@npm:^2.6.0": - version: 2.6.0 - resolution: "@medusajs/workflows-sdk@npm:2.6.0" +"@medusajs/workflows-sdk@npm:2.6.1, @medusajs/workflows-sdk@npm:^2.5.0, @medusajs/workflows-sdk@npm:^2.6.1": + version: 2.6.1 + resolution: "@medusajs/workflows-sdk@npm:2.6.1" dependencies: - "@medusajs/modules-sdk": "npm:^2.6.0" - "@medusajs/orchestration": "npm:^2.6.0" - "@medusajs/types": "npm:^2.6.0" - "@medusajs/utils": "npm:^2.6.0" + "@medusajs/modules-sdk": "npm:2.6.1" + "@medusajs/orchestration": "npm:2.6.1" + "@medusajs/types": "npm:2.6.1" + "@medusajs/utils": "npm:2.6.1" ulid: "npm:^2.3.0" peerDependencies: "@mikro-orm/core": 6.4.3 @@ -4252,7 +4254,7 @@ __metadata: awilix: ^8.0.1 express: ^4.21.0 pg: ^8.13.0 - checksum: 10c0/71cbc9e0d6c909becbfc752af53e619bf8b9318e602c7e9deded02220109c8bc5c50aaabe768051b57143094193dcd06f5f6a6df340394900004a853ff0c1397 + checksum: 10c0/8588af3e36cc8eb69e4d7fcb546cdaa5a80b8b73e4750f3d141ba03300e4e1dd9907ee171a9d7a551e478df143e0a4aced8eb7cfeb3e1ec56ba3aa13ae4a66a2 languageName: node linkType: hard @@ -16418,7 +16420,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.6.2, typescript@npm:^5.7.2, typescript@npm:^5.7.3": +"typescript@npm:5.7.3, typescript@npm:^5.6.2, typescript@npm:^5.7.2, typescript@npm:^5.7.3": version: 5.7.3 resolution: "typescript@npm:5.7.3" bin: @@ -16428,7 +16430,7 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.6.2#optional!builtin, typescript@patch:typescript@npm%3A^5.7.2#optional!builtin, typescript@patch:typescript@npm%3A^5.7.3#optional!builtin": +"typescript@patch:typescript@npm%3A5.7.3#optional!builtin, typescript@patch:typescript@npm%3A^5.6.2#optional!builtin, typescript@patch:typescript@npm%3A^5.7.2#optional!builtin, typescript@patch:typescript@npm%3A^5.7.3#optional!builtin": version: 5.7.3 resolution: "typescript@patch:typescript@npm%3A5.7.3#optional!builtin::version=5.7.3&hash=5786d5" bin: From 6e6cd866eb56f8c26c8688c7beddd5a1814bdc77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antony=20Dur=C3=A1n?= Date: Mon, 24 Mar 2025 09:24:56 -0600 Subject: [PATCH 28/28] refactor(page-builder): update SDK imports and type definitions - Replace ExtendedMedusaSDK with MedusaPluginsSDK for improved integration. - Update type imports to use @lambdacurry/medusa-page-builder-types across various hooks and components. - Refactor PostsDataTable and related query hooks to streamline data handling and enhance type safety. --- .../src/admin/hooks/posts-mutations.ts | 5 +- .../src/admin/hooks/posts-queries.ts | 9 +- .../components/posts-data-table/index.tsx | 3 +- .../use-post-data-table-columns.tsx | 2 +- .../posts-data-table/use-post-table-query.tsx | 430 +++++++++--------- plugins/page-builder/src/admin/sdk.ts | 4 +- 6 files changed, 237 insertions(+), 216 deletions(-) diff --git a/plugins/page-builder/src/admin/hooks/posts-mutations.ts b/plugins/page-builder/src/admin/hooks/posts-mutations.ts index 201ae042..031d427d 100644 --- a/plugins/page-builder/src/admin/hooks/posts-mutations.ts +++ b/plugins/page-builder/src/admin/hooks/posts-mutations.ts @@ -1,5 +1,4 @@ import { useMutation, useQueryClient } from '@tanstack/react-query' -import { sdk } from '../sdk' import type { AdminPageBuilderCreatePostBody, AdminPageBuilderCreatePostResponse, @@ -7,7 +6,9 @@ import type { AdminPageBuilderDuplicatePostResponse, AdminPageBuilderUpdatePostBody, AdminPageBuilderUpdatePostResponse, -} from '../../sdk/types' +} from '@lambdacurry/medusa-page-builder-types' + +import { sdk } from '../sdk' const QUERY_KEY = ['posts'] diff --git a/plugins/page-builder/src/admin/hooks/posts-queries.ts b/plugins/page-builder/src/admin/hooks/posts-queries.ts index 1eee063a..0ac1fecf 100644 --- a/plugins/page-builder/src/admin/hooks/posts-queries.ts +++ b/plugins/page-builder/src/admin/hooks/posts-queries.ts @@ -1,12 +1,11 @@ import { useQuery } from '@tanstack/react-query' - -import { sdk } from '../sdk' -import { +import type { AdminPageBuilderListPostsQuery, AdminPageBuilderListPostsResponse, -} from '../../sdk/types' + Post, +} from '@lambdacurry/medusa-page-builder-types' -import { Post } from '../../modules/page-builder/types' +import { sdk } from '../sdk' const QUERY_KEY = ['posts'] diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx index 3ef4057a..81ae4824 100644 --- a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/index.tsx @@ -12,7 +12,7 @@ import type { Post, PostStatus, PostType, -} from "../../../../../modules/page-builder/types"; +} from "@lambdacurry/medusa-page-builder-types"; import { useAdminDeletePost, useAdminDuplicatePost, @@ -111,6 +111,7 @@ export const PostsDataTable = () => { }); const table = useDataTable({ + onRowClick: (_, row) => handleEdit(row.id), columns, data: data?.posts || [], getRowId: (row) => row.id, diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx index d1a7d019..4b6032ea 100644 --- a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-data-table-columns.tsx @@ -6,7 +6,7 @@ import { usePrompt, } from "@medusajs/ui"; import { PencilSquare, SquareTwoStackMini, Trash } from "@medusajs/icons"; -import type { Post } from "../../../../../modules/page-builder/types"; +import type { Post } from "@lambdacurry/medusa-page-builder-types"; export type ColumnActions = { onEdit?: (id: string) => void; diff --git a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-table-query.tsx b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-table-query.tsx index c024744a..0afca28b 100644 --- a/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-table-query.tsx +++ b/plugins/page-builder/src/admin/routes/content/components/posts-data-table/use-post-table-query.tsx @@ -1,211 +1,231 @@ -import { useQueryParams } from '../../../../hooks/use-query-params'; -import type { AdminPageBuilderListPostsQuery } from '../../../../../sdk/types'; -import type { PostContentMode, PostType, PostStatus } from '../../../../../modules/page-builder/types'; -import { useMemo } from 'react'; -import type { DataTableFilteringState, DataTablePaginationState, DataTableSortingState } from '@medusajs/ui'; +import { useMemo } from "react"; +import type { + DataTableFilteringState, + DataTablePaginationState, + DataTableSortingState, +} from "@medusajs/ui"; +import type { + PostContentMode, + PostType, + PostStatus, + AdminPageBuilderListPostsQuery, +} from "@lambdacurry/medusa-page-builder-types"; + +import { useQueryParams } from "../../../../hooks/use-query-params"; type UsePostTableQueryProps = { - prefix?: string; - pageSize?: number; + prefix?: string; + pageSize?: number; }; const DEFAULT_FIELDS = [ - 'id', - 'type', - 'title', - 'handle', - 'excerpt', - 'status', - 'published_at', - 'archived_at', - 'is_home_page', - 'created_at', - 'updated_at', - 'featured_image.*', -].join(','); - -export const usePostTableQuery = ({ prefix, pageSize = 10 }: UsePostTableQueryProps) => { - const { queryObject, setQueryObject } = useQueryParams( - [ - 'offset', - 'order', - 'q', - 'title', - 'handle', - 'status', - 'type', - 'content_mode', - 'is_home_page', - 'published_at', - 'archived_at', - 'created_at', - 'updated_at', - 'id', - ], - prefix, - ); - - const { - offset, - title, - handle, - status, - type, - content_mode, - is_home_page, - published_at, - archived_at, - created_at, - updated_at, - order, - q, - } = queryObject; - - // Derived state for data table - const pagination = useMemo( - () => ({ - pageSize, - pageIndex: offset ? Math.floor(Number(offset) / pageSize) : 0, - }), - [offset, pageSize], - ); - - const filtering = useMemo(() => { - const filterState: DataTableFilteringState = {}; - - if (status) { - filterState.status = status.split(','); - } - - if (type) { - filterState.type = type.split(','); - } - - return filterState; - }, [status, type]); - - const sorting = useMemo(() => { - if (order) { - const isDesc = order.startsWith('-'); - const field = isDesc ? order.substring(1) : order; - return { - id: field, - desc: isDesc, - }; - } - return null; - }, [order]); - - const searchParams: AdminPageBuilderListPostsQuery = { - limit: pageSize, - offset: offset ? Number(offset) : 0, - title: title, - handle: handle, - status: status?.split(',') as PostStatus[], - type: type?.split(',') as PostType[], - content_mode: content_mode?.split(',') as PostContentMode[], - is_home_page: is_home_page ? is_home_page === 'true' : undefined, - published_at: published_at ? JSON.parse(published_at) : undefined, - archived_at: archived_at ? JSON.parse(archived_at) : undefined, - created_at: created_at ? JSON.parse(created_at) : undefined, - updated_at: updated_at ? JSON.parse(updated_at) : undefined, - order: order, - q, - fields: DEFAULT_FIELDS, - }; - - // State updaters - const setSearchParams = (params: Partial) => { - const newQueryObject: Record = {}; - - if ('q' in params) { - newQueryObject.q = params.q || undefined; - } - - if ('status' in params) { - if (params.status && Array.isArray(params.status) && params.status.length > 0) { - newQueryObject.status = params.status.join(','); - } else if (typeof params.status === 'string') { - newQueryObject.status = params.status; - } else { - newQueryObject.status = undefined; - } - } - - if ('type' in params) { - if (params.type && Array.isArray(params.type) && params.type.length > 0) { - newQueryObject.type = params.type.join(','); - } else if (typeof params.type === 'string') { - newQueryObject.type = params.type; - } else { - newQueryObject.type = undefined; - } - } - - if ('content_mode' in params) { - if (params.content_mode && Array.isArray(params.content_mode) && params.content_mode.length > 0) { - newQueryObject.content_mode = params.content_mode.join(','); - } else if (typeof params.content_mode === 'string') { - newQueryObject.content_mode = params.content_mode; - } else { - newQueryObject.content_mode = undefined; - } - } - - if (params.is_home_page !== undefined) { - newQueryObject.is_home_page = params.is_home_page?.toString(); - } - - if (params.order !== undefined) { - newQueryObject.order = params.order || undefined; - } - - if (params.offset !== undefined) { - newQueryObject.offset = params.offset?.toString(); - } - - setQueryObject(newQueryObject); - }; - - // Simplified handlers for common operations - const setPaginationState = (newPagination: DataTablePaginationState) => { - setSearchParams({ offset: newPagination.pageIndex * pageSize }); - }; - - const setFilteringState = (newFiltering: DataTableFilteringState) => { - setSearchParams({ - status: (newFiltering.status || []) as PostStatus[], - type: (newFiltering.type || []) as PostType[], - }); - }; - - const setSortingState = (newSorting: DataTableSortingState | null) => { - if (newSorting) { - setSearchParams({ - order: `${newSorting.desc ? '-' : ''}${newSorting.id}`, - }); - } else { - setSearchParams({ order: undefined }); - } - }; - - const setSearchState = (search: string) => { - setSearchParams({ q: search || undefined }); - }; - - return { - searchParams, - raw: queryObject, - setSearchParams, - // Derived state - pagination, - filtering, - sorting, - search: q || '', - // State updaters - setPaginationState, - setFilteringState, - setSortingState, - setSearchState, - }; + "id", + "type", + "title", + "handle", + "excerpt", + "status", + "published_at", + "archived_at", + "is_home_page", + "created_at", + "updated_at", + "featured_image.*", +].join(","); + +export const usePostTableQuery = ({ + prefix, + pageSize = 10, +}: UsePostTableQueryProps) => { + const { queryObject, setQueryObject } = useQueryParams( + [ + "offset", + "order", + "q", + "title", + "handle", + "status", + "type", + "content_mode", + "is_home_page", + "published_at", + "archived_at", + "created_at", + "updated_at", + "id", + ], + prefix, + ); + + const { + offset, + title, + handle, + status, + type, + content_mode, + is_home_page, + published_at, + archived_at, + created_at, + updated_at, + order, + q, + } = queryObject; + + // Derived state for data table + const pagination = useMemo( + () => ({ + pageSize, + pageIndex: offset ? Math.floor(Number(offset) / pageSize) : 0, + }), + [offset, pageSize], + ); + + const filtering = useMemo(() => { + const filterState: DataTableFilteringState = {}; + + if (status) { + filterState.status = status.split(","); + } + + if (type) { + filterState.type = type.split(","); + } + + return filterState; + }, [status, type]); + + const sorting = useMemo(() => { + if (order) { + const isDesc = order.startsWith("-"); + const field = isDesc ? order.substring(1) : order; + return { + id: field, + desc: isDesc, + }; + } + return null; + }, [order]); + + const searchParams: AdminPageBuilderListPostsQuery = { + limit: pageSize, + offset: offset ? Number(offset) : 0, + title: title, + handle: handle, + status: status?.split(",") as PostStatus[], + type: type?.split(",") as PostType[], + content_mode: content_mode?.split(",") as PostContentMode[], + is_home_page: is_home_page ? is_home_page === "true" : undefined, + published_at: published_at ? JSON.parse(published_at) : undefined, + archived_at: archived_at ? JSON.parse(archived_at) : undefined, + created_at: created_at ? JSON.parse(created_at) : undefined, + updated_at: updated_at ? JSON.parse(updated_at) : undefined, + order: order, + q, + fields: DEFAULT_FIELDS, + }; + + // State updaters + const setSearchParams = (params: Partial) => { + const newQueryObject: Record = {}; + + if ("q" in params) { + newQueryObject.q = params.q || undefined; + } + + if ("status" in params) { + if ( + params.status && + Array.isArray(params.status) && + params.status.length > 0 + ) { + newQueryObject.status = params.status.join(","); + } else if (typeof params.status === "string") { + newQueryObject.status = params.status; + } else { + newQueryObject.status = undefined; + } + } + + if ("type" in params) { + if (params.type && Array.isArray(params.type) && params.type.length > 0) { + newQueryObject.type = params.type.join(","); + } else if (typeof params.type === "string") { + newQueryObject.type = params.type; + } else { + newQueryObject.type = undefined; + } + } + + if ("content_mode" in params) { + if ( + params.content_mode && + Array.isArray(params.content_mode) && + params.content_mode.length > 0 + ) { + newQueryObject.content_mode = params.content_mode.join(","); + } else if (typeof params.content_mode === "string") { + newQueryObject.content_mode = params.content_mode; + } else { + newQueryObject.content_mode = undefined; + } + } + + if (params.is_home_page !== undefined) { + newQueryObject.is_home_page = params.is_home_page?.toString(); + } + + if (params.order !== undefined) { + newQueryObject.order = params.order || undefined; + } + + if (params.offset !== undefined) { + newQueryObject.offset = params.offset?.toString(); + } + + setQueryObject(newQueryObject); + }; + + // Simplified handlers for common operations + const setPaginationState = (newPagination: DataTablePaginationState) => { + setSearchParams({ offset: newPagination.pageIndex * pageSize }); + }; + + const setFilteringState = (newFiltering: DataTableFilteringState) => { + setSearchParams({ + status: (newFiltering.status || []) as PostStatus[], + type: (newFiltering.type || []) as PostType[], + }); + }; + + const setSortingState = (newSorting: DataTableSortingState | null) => { + if (newSorting) { + setSearchParams({ + order: `${newSorting.desc ? "-" : ""}${newSorting.id}`, + }); + } else { + setSearchParams({ order: undefined }); + } + }; + + const setSearchState = (search: string) => { + setSearchParams({ q: search || undefined }); + }; + + return { + searchParams, + raw: queryObject, + setSearchParams, + // Derived state + pagination, + filtering, + sorting, + search: q || "", + // State updaters + setPaginationState, + setFilteringState, + setSortingState, + setSearchState, + }; }; diff --git a/plugins/page-builder/src/admin/sdk.ts b/plugins/page-builder/src/admin/sdk.ts index 11ed87df..39d900ed 100644 --- a/plugins/page-builder/src/admin/sdk.ts +++ b/plugins/page-builder/src/admin/sdk.ts @@ -1,10 +1,10 @@ -import { ExtendedMedusaSDK } from '../sdk' +import { MedusaPluginsSDK } from '@lambdacurry/medusa-plugins-sdk' declare const __BACKEND_URL__: string | undefined export const backendUrl = __BACKEND_URL__ ?? 'http://localhost:9000' -export const sdk = new ExtendedMedusaSDK({ +export const sdk = new MedusaPluginsSDK({ baseUrl: backendUrl, auth: { type: 'session',