diff --git a/apps/studio/components/interfaces/Replication/DeletePublicationModal.tsx b/apps/studio/components/interfaces/Replication/DeletePublicationModal.tsx
new file mode 100644
index 00000000000..1f91ad14851
--- /dev/null
+++ b/apps/studio/components/interfaces/Replication/DeletePublicationModal.tsx
@@ -0,0 +1,54 @@
+import { useParams } from 'common'
+import { useDeletePublicationMutation } from 'data/replication/delete-publication-mutation'
+import { toast } from 'sonner'
+import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal'
+
+export type DeletePublicationModalProps = {
+ visible: boolean
+ title: string
+ sourceId: number
+ publicationName: string
+ onClose: () => void
+}
+
+export const DeletePublicationModal = ({
+ visible,
+ title,
+ sourceId,
+ publicationName,
+ onClose,
+}: DeletePublicationModalProps) => {
+ const { ref } = useParams()
+ const { mutate: deletePublication, isLoading: isCreating } = useDeletePublicationMutation({
+ onSuccess: (res) => {
+ toast.success('Successfully deleted publication')
+ onClose()
+ },
+ })
+ const onConfirm = () => {
+ deletePublication({
+ projectRef: ref!,
+ sourceId,
+ publicationName,
+ })
+ }
+ return (
+ {
+ onClose()
+ }}
+ onConfirm={onConfirm}
+ >
+
+
+ Are you sure you want to delete the selected publication? This action cannot be undone.
+
+
+
+ )
+}
diff --git a/apps/studio/components/interfaces/Replication/Publications.tsx b/apps/studio/components/interfaces/Replication/Publications.tsx
index b083272d55b..b9774a17aba 100644
--- a/apps/studio/components/interfaces/Replication/Publications.tsx
+++ b/apps/studio/components/interfaces/Replication/Publications.tsx
@@ -10,6 +10,7 @@ import { Button } from 'ui'
import { useState } from 'react'
import CreatePublicationModal from './CreatePublicationModal'
import { toast } from 'sonner'
+import { DeletePublicationModal } from './DeletePublicationModal'
export const ReplicationPublications = () => {
const { ref } = useParams()
@@ -17,6 +18,8 @@ export const ReplicationPublications = () => {
projectRef: ref,
})
const [showCreatePublicationModal, setShowCreatePublicationModal] = useState(false)
+ const [showDeletePublicationModal, setShowDeletePublicationModal] = useState(false)
+ const [publicationToDelete, setPublicationToDelete] = useState('')
const sources = data ?? []
let source_id = null
@@ -84,10 +87,18 @@ export const ReplicationPublications = () => {
{pub.name}
{pub.tables.length}
-
+
-
+
))
@@ -101,9 +112,16 @@ export const ReplicationPublications = () => {
setShowCreatePublicationModal(false)}
/>
+ setShowDeletePublicationModal(false)}
+ />
>
)
}
diff --git a/apps/studio/data/replication/delete-publication-mutation.ts b/apps/studio/data/replication/delete-publication-mutation.ts
new file mode 100644
index 00000000000..5fac136e151
--- /dev/null
+++ b/apps/studio/data/replication/delete-publication-mutation.ts
@@ -0,0 +1,64 @@
+import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
+import { toast } from 'sonner'
+
+import type { ResponseError } from 'types'
+import { replicationKeys } from './keys'
+import { handleError, del } from 'data/fetchers'
+
+export type DeletePublicationParams = {
+ projectRef: string
+ sourceId: number
+ publicationName: string
+}
+
+async function deletePublication(
+ { projectRef, sourceId, publicationName: publication_name }: DeletePublicationParams,
+ signal?: AbortSignal
+) {
+ if (!projectRef) throw new Error('projectRef is required')
+
+ const { data, error } = await del(
+ '/platform/replication/{ref}/sources/{source_id}/publications/{publication_name}',
+ {
+ params: { path: { ref: projectRef, source_id: sourceId, publication_name } },
+ signal,
+ }
+ )
+ if (error) {
+ handleError(error)
+ }
+
+ return data
+}
+
+type DeletePublicationData = Awaited>
+
+export const useDeletePublicationMutation = ({
+ onSuccess,
+ onError,
+ ...options
+}: Omit<
+ UseMutationOptions,
+ 'mutationFn'
+> = {}) => {
+ const queryClient = useQueryClient()
+
+ return useMutation(
+ (vars) => deletePublication(vars),
+ {
+ async onSuccess(data, variables, context) {
+ const { projectRef, sourceId } = variables
+ await queryClient.invalidateQueries(replicationKeys.publications(projectRef, sourceId))
+ await onSuccess?.(data, variables, context)
+ },
+ async onError(data, variables, context) {
+ if (onError === undefined) {
+ toast.error(`Failed to delete publication: ${data.message}`)
+ } else {
+ onError(data, variables, context)
+ }
+ },
+ ...options,
+ }
+ )
+}
diff --git a/packages/api-types/types/api.d.ts b/packages/api-types/types/api.d.ts
index 2e960d6adb7..aa27b26af3e 100644
--- a/packages/api-types/types/api.d.ts
+++ b/packages/api-types/types/api.d.ts
@@ -3331,6 +3331,10 @@ export interface paths {
/** Creates a publication */
post: operations['ReplicationSourcesController_createPublication']
}
+ '/platform/replication/{ref}/sources/{source_id}/publications/{publication_name}': {
+ /** Deletes a publication */
+ delete: operations['ReplicationSourcesController_deletePublication']
+ }
'/platform/replication/{ref}/sources/{source_id}/tables': {
/** Gets source tables */
get: operations['ReplicationSourcesController_getTables']
@@ -8642,7 +8646,6 @@ export interface components {
publish_update?: boolean
tables?: string[] | null
}
- CreatePublicationResponse: Record
CreateReplicationPublicationBody: {
/** @description Publication name */
name: string
@@ -21680,9 +21683,7 @@ export interface operations {
}
responses: {
201: {
- content: {
- 'application/json': components['schemas']['CreatePublicationResponse']
- }
+ content: never
}
/** @description Failed to create publication */
500: {
@@ -21690,6 +21691,28 @@ export interface operations {
}
}
}
+ /** Deletes a publication */
+ ReplicationSourcesController_deletePublication: {
+ parameters: {
+ path: {
+ /** @description Project ref */
+ ref: string
+ /** @description Source id */
+ source_id: number
+ /** @description Publication name */
+ publication_name: string
+ }
+ }
+ responses: {
+ 200: {
+ content: never
+ }
+ /** @description Failed to delete publication */
+ 500: {
+ content: never
+ }
+ }
+ }
/** Gets source tables */
ReplicationSourcesController_getTables: {
parameters: {