Files
supabase__supabase/apps/studio/data/replication/publication-create-mutation.ts
Danny White 3418975b70 feat(studio): configure publication partition handling (#49845)
## What kind of change does this PR introduce?

Small Pipelines feature. Stacked on #49844.

## What is the current behavior?

New publications always publish changes from partitioned tables through
their parent table. The creation sheet does not expose the v2 API option
that controls this behavior.

## What is the new behavior?

Adds a default-on Publish partitions as the parent table checkbox to the
publication sheet. Turning it off submits publish_via_partition_root as
false so each partition can appear as a separate destination table.

## To test

1. Open the pipeline creation sheet and choose to create a publication.
2. Confirm Publish partitions as the parent table is selected by
default.
3. Create a publication and confirm publish_via_partition_root is true.
4. Repeat with the option cleared and confirm publish_via_partition_root
is false.
5. Confirm the selected tables and publication name are unchanged by the
option.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Added a “Publish partitions as the parent table” option when creating
publications.
- The option is enabled by default and can be turned off before
submitting the publication.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-09-08 14:03:18 +10:00

73 lines
2.1 KiB
TypeScript

import { useMutation, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import { replicationKeys } from './keys'
import { handleError, put } from '@/data/fetchers'
import type { ResponseError, UseCustomMutationOptions } from '@/types'
export type CreatePublicationParams = {
projectRef: string
sourceId: number
name: string
tableIds: number[]
publishViaPartitionRoot?: boolean
}
async function createPublication(
{ projectRef, sourceId, name, tableIds, publishViaPartitionRoot = true }: CreatePublicationParams,
signal?: AbortSignal
) {
if (!projectRef) throw new Error('projectRef is required')
const { data, error } = await put(
'/platform/replication/v2/{ref}/sources/{source_id}/publications/{publication_name}',
{
params: { path: { ref: projectRef, source_id: sourceId, publication_name: name } },
body: {
type: 'tables',
tables: tableIds.map((id) => ({ id })),
operations: ['insert', 'update', 'delete', 'truncate'],
publish_via_partition_root: publishViaPartitionRoot,
},
signal,
}
)
if (error) {
handleError(error)
}
return data
}
type CreatePublicationData = Awaited<ReturnType<typeof createPublication>>
export const useCreatePublicationMutation = ({
onSuccess,
onError,
...options
}: Omit<
UseCustomMutationOptions<CreatePublicationData, ResponseError, CreatePublicationParams>,
'mutationFn'
> = {}) => {
const queryClient = useQueryClient()
return useMutation<CreatePublicationData, ResponseError, CreatePublicationParams>({
mutationFn: (vars) => createPublication(vars),
async onSuccess(data, variables, context) {
const { projectRef, sourceId } = variables
await queryClient.invalidateQueries({
queryKey: replicationKeys.publications(projectRef, sourceId),
})
await onSuccess?.(data, variables, context)
},
async onError(data, variables, context) {
if (onError === undefined) {
toast.error(`Failed to create publication: ${data.message}`)
} else {
onError(data, variables, context)
}
},
...options,
})
}