diff --git a/lib/adapters/REST/endpoints/bulk-action.ts b/lib/adapters/REST/endpoints/bulk-action.ts index cc63d1542f..e032a597a9 100644 --- a/lib/adapters/REST/endpoints/bulk-action.ts +++ b/lib/adapters/REST/endpoints/bulk-action.ts @@ -5,6 +5,9 @@ import type { BulkActionPublishPayload, BulkActionUnpublishPayload, BulkActionValidatePayload, + PublishBulkActionV2Payload, + UnpublishBulkActionV2Payload, + ValidateBulkActionV2Payload, } from '../../../entities/bulk-action' import type { RestEndpoint } from '../types' import * as raw from './raw' @@ -54,3 +57,53 @@ export const validate: RestEndpoint<'BulkAction', 'validate'> = ( payload ) } + +export const getV2: RestEndpoint<'BulkAction', 'getV2'> = ( + http: AxiosInstance, + params: GetBulkActionParams +) => { + return raw.get( + http, + `/spaces/${params.spaceId}/environments/${params.environmentId}/bulk_actions/${params.bulkActionId}` + ) +} + +export const publishV2: RestEndpoint<'BulkAction', 'publishV2'> = ( + http: AxiosInstance, + params: GetSpaceEnvironmentParams, + payload: PublishBulkActionV2Payload<'add'> +): Promise>> => { + return raw.post( + http, + `/spaces/${params.spaceId}/environments/${params.environmentId}/bulk_actions`, + payload + ) +} + +export const unpublishV2: RestEndpoint<'BulkAction', 'unpublishV2'> = ( + http: AxiosInstance, + params: GetSpaceEnvironmentParams, + payload: PublishBulkActionV2Payload<'remove'> | UnpublishBulkActionV2Payload +): Promise< + BulkActionProps | UnpublishBulkActionV2Payload> +> => { + return raw.post( + http, + `/spaces/${params.spaceId}/environments/${params.environmentId}/bulk_actions`, + payload + ) +} + +export const validateV2: RestEndpoint<'BulkAction', 'validateV2'> = ( + http: AxiosInstance, + params: GetSpaceEnvironmentParams, + payload: ValidateBulkActionV2Payload<'add'> | ValidateBulkActionV2Payload<'remove'> +): Promise< + BulkActionProps | ValidateBulkActionV2Payload<'remove'>> +> => { + return raw.post( + http, + `/spaces/${params.spaceId}/environments/${params.environmentId}/bulk_actions`, + payload + ) +} diff --git a/lib/common-types.ts b/lib/common-types.ts index ff9f865b5d..7d7ee10c91 100644 --- a/lib/common-types.ts +++ b/lib/common-types.ts @@ -40,7 +40,11 @@ import type { BulkActionProps, BulkActionPublishPayload, BulkActionUnpublishPayload, + BulkActionV2Payload, BulkActionValidatePayload, + PublishBulkActionV2Payload, + UnpublishBulkActionV2Payload, + ValidateBulkActionV2Payload, } from './entities/bulk-action' import type { CommentProps, @@ -479,6 +483,10 @@ type MRInternal = { (opts: MROpts<'BulkAction', 'publish', UA>): MRReturn<'BulkAction', 'publish'> (opts: MROpts<'BulkAction', 'unpublish', UA>): MRReturn<'BulkAction', 'unpublish'> (opts: MROpts<'BulkAction', 'validate', UA>): MRReturn<'BulkAction', 'validate'> + (opts: MROpts<'BulkAction', 'getV2', UA>): MRReturn<'BulkAction', 'getV2'> + (opts: MROpts<'BulkAction', 'publishV2', UA>): MRReturn<'BulkAction', 'publishV2'> + (opts: MROpts<'BulkAction', 'unpublishV2', UA>): MRReturn<'BulkAction', 'unpublishV2'> + (opts: MROpts<'BulkAction', 'validateV2', UA>): MRReturn<'BulkAction', 'validateV2'> (opts: MROpts<'Comment', 'get', UA>): MRReturn<'Comment', 'get'> (opts: MROpts<'Comment', 'getMany', UA>): MRReturn<'Comment', 'getMany'> @@ -1197,6 +1205,27 @@ export type MRActions = { payload: BulkActionValidatePayload return: BulkActionProps } + getV2: { + params: GetBulkActionParams + return: BulkActionProps + } + publishV2: { + params: GetSpaceEnvironmentParams + payload: PublishBulkActionV2Payload<'add'> + return: BulkActionProps> + } + unpublishV2: { + params: GetSpaceEnvironmentParams + payload: PublishBulkActionV2Payload<'remove'> | UnpublishBulkActionV2Payload + return: BulkActionProps | UnpublishBulkActionV2Payload> + } + validateV2: { + params: GetSpaceEnvironmentParams + payload: ValidateBulkActionV2Payload<'add'> | ValidateBulkActionV2Payload<'remove'> + return: BulkActionProps< + ValidateBulkActionV2Payload<'add'> | ValidateBulkActionV2Payload<'remove'> + > + } } Comment: { get: diff --git a/lib/entities/bulk-action.ts b/lib/entities/bulk-action.ts index ca697c513b..5ced9b211c 100644 --- a/lib/entities/bulk-action.ts +++ b/lib/entities/bulk-action.ts @@ -69,6 +69,49 @@ export interface BulkActionPublishPayload extends MakeRequestPayload { } } +interface AddFieldsEntity | VersionedLink> { + entity: L + add?: { + fields: Record<'*', string[]> + } +} + +interface RemoveFieldsEntity | VersionedLink> { + entity: L + remove?: { + fields: Record<'*', string[]> + } +} +type BulkActionEntity | VersionedLink> = { + entity: L +} + +export interface PublishBulkActionV2Payload { + action: 'publish' + entities: PublishActionType extends 'remove' + ? RemoveFieldsEntity>[] + : AddFieldsEntity>[] +} + +export interface ValidateBulkActionV2Payload { + action: 'validate' + entities: PublishActionType extends 'remove' + ? RemoveFieldsEntity>[] + : AddFieldsEntity>[] +} + +export interface UnpublishBulkActionV2Payload { + action: 'unpublish' + entities: BulkActionEntity>[] +} + +export type BulkActionV2Payload = + | PublishBulkActionV2Payload<'add'> + | PublishBulkActionV2Payload<'remove'> + | UnpublishBulkActionV2Payload + | ValidateBulkActionV2Payload<'add'> + | ValidateBulkActionV2Payload<'remove'> + export type BulkActionSysProps = { id: string type: 'BulkAction' @@ -81,7 +124,7 @@ export type BulkActionSysProps = { } /** The object returned by the BulkActions API */ -export interface BulkActionProps { +export interface BulkActionProps { sys: BulkActionSysProps action: BulkActionType /** original payload when BulkAction was created */ @@ -120,7 +163,7 @@ function createBulkActionApi(makeRequest: MakeRequest) { params, }).then((bulkAction) => wrapBulkAction(makeRequest, bulkAction)) }, - async waitProcessing( + async waitProcessing( options?: AsyncActionProcessingOptions ): Promise> { return pollAsyncActionStatus>(async () => this.get(), options) @@ -128,7 +171,7 @@ function createBulkActionApi(makeRequest: MakeRequest) { } } -export interface BulkAction +export interface BulkAction extends BulkActionProps, BulkActionApiMethods, DefaultElements> {} @@ -139,9 +182,9 @@ export interface BulkAction * @param data - Raw BulkAction data * @return Wrapped BulkAction data */ -export function wrapBulkAction( +export function wrapBulkAction( makeRequest: MakeRequest, - data: BulkActionProps + data: BulkActionProps ): BulkAction { const bulkAction = toPlainObject(copy(data)) const bulkActionWithApiMethods = enhanceWithMethods( diff --git a/lib/export-types.ts b/lib/export-types.ts index c550989a15..bc4514717b 100644 --- a/lib/export-types.ts +++ b/lib/export-types.ts @@ -80,6 +80,10 @@ export type { BulkActionType, BulkActionUnpublishPayload, BulkActionValidatePayload, + BulkActionV2Payload, + PublishBulkActionV2Payload, + UnpublishBulkActionV2Payload, + ValidateBulkActionV2Payload, } from './entities/bulk-action' export type { Comment, diff --git a/lib/methods/bulk-action.ts b/lib/methods/bulk-action.ts index 0ea7056d4a..547f056f60 100644 --- a/lib/methods/bulk-action.ts +++ b/lib/methods/bulk-action.ts @@ -1,4 +1,8 @@ -import type { BulkActionPayload, BulkActionProps } from '../entities/bulk-action' +import type { + BulkActionPayload, + BulkActionProps, + BulkActionV2Payload, +} from '../entities/bulk-action' import type { PlainClientAPI } from '../plain/common-types' import type { AsyncActionProcessingOptions } from './action' import { pollAsyncActionStatus } from './action' @@ -27,3 +31,20 @@ export async function waitForBulkActionProcessing( + { plainClient, spaceId, environmentId, bulkActionId }: PlainOptions, + options?: AsyncActionProcessingOptions +): Promise> { + return pollAsyncActionStatus( + async () => + plainClient.bulkAction.getV2({ + bulkActionId, + spaceId, + environmentId, + }), + options + ) +} diff --git a/lib/plain/common-types.ts b/lib/plain/common-types.ts index 72ee1448d3..603d7984f6 100644 --- a/lib/plain/common-types.ts +++ b/lib/plain/common-types.ts @@ -35,7 +35,11 @@ import type { BulkActionProps, BulkActionPublishPayload, BulkActionUnpublishPayload, + BulkActionV2Payload, BulkActionValidatePayload, + PublishBulkActionV2Payload, + UnpublishBulkActionV2Payload, + ValidateBulkActionV2Payload, } from '../entities/bulk-action' import type { ContentTypeProps, CreateContentTypeProps } from '../entities/content-type' import type { CreateEntryProps, EntryProps, EntryReferenceProps } from '../entities/entry' @@ -226,6 +230,21 @@ export type PlainClientAPI = { params: GetSpaceEnvironmentParams, payload: BulkActionValidatePayload ): Promise> + getV2(params: GetBulkActionParams): Promise> + publishV2( + params: GetSpaceEnvironmentParams, + payload: PublishBulkActionV2Payload<'add'> + ): Promise>> + unpublishV2( + params: GetSpaceEnvironmentParams, + payload: PublishBulkActionV2Payload<'remove'> | UnpublishBulkActionV2Payload + ): Promise | UnpublishBulkActionV2Payload>> + validateV2( + params: GetSpaceEnvironmentParams, + payload: ValidateBulkActionV2Payload<'add'> | ValidateBulkActionV2Payload<'remove'> + ): Promise< + BulkActionProps | ValidateBulkActionV2Payload<'remove'>> + > } comment: CommentPlainClientAPI concept: ConceptPlainClientAPI diff --git a/lib/plain/plain-client.ts b/lib/plain/plain-client.ts index c31007e54f..0d58d78dcc 100644 --- a/lib/plain/plain-client.ts +++ b/lib/plain/plain-client.ts @@ -186,6 +186,10 @@ export const createPlainClient = ( publish: wrap(wrapParams, 'BulkAction', 'publish'), unpublish: wrap(wrapParams, 'BulkAction', 'unpublish'), validate: wrap(wrapParams, 'BulkAction', 'validate'), + getV2: wrap(wrapParams, 'BulkAction', 'getV2'), + publishV2: wrap(wrapParams, 'BulkAction', 'publishV2'), + unpublishV2: wrap(wrapParams, 'BulkAction', 'unpublishV2'), + validateV2: wrap(wrapParams, 'BulkAction', 'validateV2'), }, comment: { get: wrap(wrapParams, 'Comment', 'get') as PlainClientAPI['comment']['get'], diff --git a/test/integration/bulk-action-integration.test.ts b/test/integration/bulk-action-integration.test.ts index 0ff2a3ab38..95ca5d9a38 100644 --- a/test/integration/bulk-action-integration.test.ts +++ b/test/integration/bulk-action-integration.test.ts @@ -5,14 +5,22 @@ import type { BulkActionPublishPayload, BulkActionUnpublishPayload, BulkActionValidatePayload, + UnpublishBulkActionV2Payload, } from '../../lib/contentful-management' import type { Environment, Space } from '../../lib/contentful-management' -import { waitForBulkActionProcessing } from '../../lib/methods/bulk-action' +import { + waitForBulkActionProcessing, + waitForBulkActionV2Processing, +} from '../../lib/methods/bulk-action' import { TestDefaults } from '../defaults' import { getDefaultSpace, initPlainClient, timeoutToCalmRateLimiting } from '../helpers' import { makeLink, makeVersionedLink } from '../utils' +import { + PublishBulkActionV2Payload, + ValidateBulkActionV2Payload, +} from '../../lib/entities/bulk-action' -describe('BulkActions Api', () => { +describe('BulkActions Api v1', () => { let testSpace: Space let testEnvironment: Environment @@ -257,3 +265,83 @@ describe('BulkActions Api', () => { }) }) }) + +describe('BulkActions Api v2 (Plain Client only)', () => { + afterAll(timeoutToCalmRateLimiting) + + const defaultParams = { + environmentId: TestDefaults.environmentId, + spaceId: TestDefaults.spaceId, + } + const plainClient = initPlainClient(defaultParams) + + it('bulkAction.publishV2', async () => { + const entry = await plainClient.entry.get({ entryId: TestDefaults.entry.testEntryBulkActionId }) + + const bulkActionInProgress = await plainClient.bulkAction.publishV2(defaultParams, { + action: 'publish', + entities: [ + { + entity: makeVersionedLink('Entry', entry.sys.id, entry.sys.version), + add: { fields: { '*': ['en-US'] } }, + }, + ], + }) + + const bulkActionCompleted = await waitForBulkActionV2Processing< + PublishBulkActionV2Payload<'add'> + >({ + ...defaultParams, + plainClient, + bulkActionId: bulkActionInProgress.sys.id, + }) + + expect(bulkActionCompleted.sys.status).toBe('succeeded') + expect(bulkActionCompleted.action).toBe('publish') + }) + + it('bulkAction.unpublishV2', async () => { + const entry = await plainClient.entry.get({ entryId: TestDefaults.entry.testEntryBulkActionId }) + + const bulkActionInProgress = await plainClient.bulkAction.unpublishV2(defaultParams, { + action: 'unpublish', + entities: [ + { + entity: makeLink('Entry', entry.sys.id), + }, + ], + }) + + const bulkActionCompleted = await waitForBulkActionV2Processing({ + ...defaultParams, + plainClient, + bulkActionId: bulkActionInProgress.sys.id, + }) + + expect(bulkActionCompleted.sys.status).toBe('succeeded') + expect(bulkActionCompleted.action).toBe('unpublish') + }) + + it('bulkAction.validateV2', async () => { + const entry = await plainClient.entry.get({ entryId: TestDefaults.entry.testEntryBulkActionId }) + + const bulkActionInProgress = await plainClient.bulkAction.validateV2(defaultParams, { + action: 'validate', + entities: [ + { + entity: makeLink('Entry', entry.sys.id), + add: { fields: { '*': ['en-US'] } }, + }, + ], + }) + + const bulkActionCompleted = await waitForBulkActionV2Processing({ + ...defaultParams, + plainClient, + bulkActionId: bulkActionInProgress.sys.id, + }) + + expect(bulkActionCompleted.sys.status).toBe('succeeded') + expect(bulkActionCompleted.action).toBe('validate') + }) +})