diff --git a/lib/adapters/REST/endpoints/component-type.ts b/lib/adapters/REST/endpoints/component-type.ts index 377f30034..613948588 100644 --- a/lib/adapters/REST/endpoints/component-type.ts +++ b/lib/adapters/REST/endpoints/component-type.ts @@ -1,6 +1,10 @@ import type { RawAxiosRequestHeaders } from 'axios' import type { AxiosInstance } from 'contentful-sdk-core' -import type { CollectionProp, GetSpaceEnvironmentParams } from '../../../common-types' +import type { + CollectionProp, + GetComponentTypeParams, + GetSpaceEnvironmentParams, +} from '../../../common-types' import type { ComponentTypeProps, ComponentTypeQueryOptions, @@ -31,3 +35,16 @@ export const get: RestEndpoint<'ComponentType', 'get'> = ( headers, }) } + +export const unpublish: RestEndpoint<'ComponentType', 'unpublish'> = ( + http: AxiosInstance, + params: GetComponentTypeParams & { version: number }, + headers?: RawAxiosRequestHeaders, +) => { + return raw.del(http, `${getBaseUrl(params)}/${params.componentTypeId}/published`, { + headers: { + 'X-Contentful-Version': params.version, + ...headers, + }, + }) +} diff --git a/lib/common-types.ts b/lib/common-types.ts index 67a527700..f4c0e57ed 100644 --- a/lib/common-types.ts +++ b/lib/common-types.ts @@ -576,6 +576,7 @@ type MRInternal = { (opts: MROpts<'ComponentType', 'getMany', UA>): MRReturn<'ComponentType', 'getMany'> (opts: MROpts<'ComponentType', 'get', UA>): MRReturn<'ComponentType', 'get'> + (opts: MROpts<'ComponentType', 'unpublish', UA>): MRReturn<'ComponentType', 'unpublish'> (opts: MROpts<'Concept', 'get', UA>): MRReturn<'Concept', 'get'> (opts: MROpts<'Concept', 'getMany', UA>): MRReturn<'Concept', 'getMany'> @@ -1478,6 +1479,10 @@ export type MRActions = { params: GetSpaceEnvironmentParams & { componentId: string } return: ComponentTypeProps } + unpublish: { + params: GetComponentTypeParams & { version: number } + return: ComponentTypeProps + } } Concept: { create: { @@ -2610,6 +2615,7 @@ export type GetBulkActionParams = GetSpaceEnvironmentParams & { bulkActionId: st export type GetCommentParams = (GetEntryParams | GetCommentParentEntityParams) & { commentId: string } +export type GetComponentTypeParams = GetSpaceEnvironmentParams & { componentTypeId: string } export type GetContentTypeParams = GetSpaceEnvironmentParams & { contentTypeId: string } export type GetEditorInterfaceParams = GetSpaceEnvironmentParams & { contentTypeId: string } export type GetEntryParams = GetSpaceEnvironmentParams & { entryId: string } diff --git a/lib/plain/entities/component-type.ts b/lib/plain/entities/component-type.ts index 6e8fbc6e8..e2b2c1f22 100644 --- a/lib/plain/entities/component-type.ts +++ b/lib/plain/entities/component-type.ts @@ -1,4 +1,8 @@ -import type { GetSpaceEnvironmentParams, CollectionProp } from '../../common-types' +import type { + GetSpaceEnvironmentParams, + GetComponentTypeParams, + CollectionProp, +} from '../../common-types' import type { ComponentTypeQueryOptions, ComponentTypeProps } from '../../entities/component-type' import type { OptionalDefaults } from '../wrappers/wrap' @@ -48,4 +52,23 @@ export type ComponentTypePlainClientAPI = { get( params: OptionalDefaults, ): Promise + + /** + * Unpublishes a component type + * @param params the space, environment, and component type IDs + * @returns the unpublished component type + * @throws if the request fails, or the component type is not found + * @internal - Experimental endpoint, subject to breaking changes without notice + * @example + * ```javascript + * const componentType = await client.componentType.unpublish({ + * spaceId: '', + * environmentId: '', + * componentTypeId: '', + * }); + * ``` + */ + unpublish( + params: OptionalDefaults, + ): Promise } diff --git a/lib/plain/plain-client.ts b/lib/plain/plain-client.ts index c52c61d1e..5aac00abd 100644 --- a/lib/plain/plain-client.ts +++ b/lib/plain/plain-client.ts @@ -226,6 +226,7 @@ export const createPlainClient = ( componentType: { getMany: wrap(wrapParams, 'ComponentType', 'getMany'), get: wrap(wrapParams, 'ComponentType', 'get'), + unpublish: wrap(wrapParams, 'ComponentType', 'unpublish'), }, contentType: { get: wrap(wrapParams, 'ContentType', 'get'), diff --git a/test/unit/adapters/REST/endpoints/component-type.test.ts b/test/unit/adapters/REST/endpoints/component-type.test.ts index 16371af0a..1e954f519 100644 --- a/test/unit/adapters/REST/endpoints/component-type.test.ts +++ b/test/unit/adapters/REST/endpoints/component-type.test.ts @@ -102,4 +102,42 @@ describe('Rest ComponentType', { concurrent: true }, () => { ) }) }) + + test('unpublish calls correct URL with DELETE method', async () => { + const mockResponse = { + sys: { + id: 'ct123', + type: 'ComponentType', + version: 2, + space: { sys: { type: 'Link', linkType: 'Space', id: 'space123' } }, + environment: { sys: { type: 'Link', linkType: 'Environment', id: 'master' } }, + }, + name: 'Test Component', + description: 'A test component type', + viewports: [], + contentProperties: [], + designProperties: [], + dimensionKeyMap: { designProperties: {} }, + } + + const { httpMock, adapterMock } = setupRestAdapter(Promise.resolve({ data: mockResponse })) + + return adapterMock + .makeRequest({ + entityType: 'ComponentType', + action: 'unpublish', + userAgent: 'mocked', + params: { + spaceId: 'space123', + environmentId: 'master', + componentTypeId: 'ct123', + }, + }) + .then((r) => { + expect(r).to.eql(mockResponse) + expect(httpMock.delete.mock.calls[0][0]).to.eql( + '/spaces/space123/environments/master/component_types/ct123/published', + ) + }) + }) })