diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c51b844..5db03f2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [v1.31.0](https://github.com/contentstack/contentstack-management-javascript/tree/v1.31.0) (2026-07-27) + +- Enh + - Entry variants: `contentType(...).entry(...).variants(variantUidOrUids, branchName?)` — optional second argument sets the CMA `branch` header for that variants scope (branch UID or alias). First argument accepts a variant UID string or an array of UIDs (comma-separated in the request path). Omitting `branchName` preserves previous behavior. + - Entry variants: added `variants(uid).publish()` and `variants(uid).unpublish()`, calling the entry publish/unpublish endpoints with the variant payload nested under `entry`. + - `publish()`/`unpublish()` (entry and entry variants) accept optional `headers` and `params`, merged into the underlying HTTP request. +- Test + - Unit tests and sanity API tests for entry variants with an explicit branch, and for the new variant `publish()`/`unpublish()` methods. + ## [v1.30.4](https://github.com/contentstack/contentstack-management-javascript/tree/v1.30.4) (2026-06-29) - Update dependencies diff --git a/lib/entity.js b/lib/entity.js index 6bd45e4c..005e0550 100644 --- a/lib/entity.js +++ b/lib/entity.js @@ -13,7 +13,7 @@ import ContentstackCollection from './contentstackCollection' * await publishFn.call(entryInstance, { publishDetails: {...}, locale: 'en-us' }) */ export const publish = (http, type) => { - return async function ({ publishDetails, locale = null, version = null, scheduledAt = null }) { + return async function ({ publishDetails, locale = null, version = null, scheduledAt = null, headers: extraHeaders = {}, params = {} }) { const url = this.urlPath + '/publish' const headers = { headers: { @@ -22,7 +22,10 @@ export const publish = (http, type) => { } || {} const httpBody = {} httpBody[type] = cloneDeep(publishDetails) - return publishUnpublish(http, url, httpBody, headers, locale, version, scheduledAt) + return publishUnpublish(http, url, httpBody, headers, locale, version, scheduledAt, { + headers: extraHeaders, + params + }) } } @@ -36,7 +39,7 @@ export const publish = (http, type) => { * await unpublishFn.call(entryInstance, { publishDetails: {...}, locale: 'en-us' }) */ export const unpublish = (http, type) => { - return async function ({ publishDetails, locale = null, version = null, scheduledAt = null }) { + return async function ({ publishDetails, locale = null, version = null, scheduledAt = null, headers: extraHeaders = {}, params = {} }) { const url = this.urlPath + '/unpublish' const headers = { headers: { @@ -45,7 +48,10 @@ export const unpublish = (http, type) => { } || {} const httpBody = {} httpBody[type] = cloneDeep(publishDetails) - return publishUnpublish(http, url, httpBody, headers, locale, version, scheduledAt) + return publishUnpublish(http, url, httpBody, headers, locale, version, scheduledAt, { + headers: extraHeaders, + params + }) } } @@ -58,11 +64,12 @@ export const unpublish = (http, type) => { * @param {string|null} locale - Locale code. * @param {number|null} version - Version number. * @param {string|null} scheduledAt - Scheduled date/time in ISO format. + * @param {Object} [configExtras={}] - Optional `{ headers, params }` merged into the axios request (stack headers stay in `headers.headers`). * @returns {Promise} Promise that resolves to response data. * @async * @private */ -export const publishUnpublish = async (http, url, httpBody, headers, locale = null, version = null, scheduledAt = null) => { +export const publishUnpublish = async (http, url, httpBody, headers, locale = null, version = null, scheduledAt = null, configExtras = {}) => { if (locale !== null) { httpBody.locale = locale } @@ -72,8 +79,18 @@ export const publishUnpublish = async (http, url, httpBody, headers, locale = nu if (scheduledAt !== null) { httpBody.scheduled_at = scheduledAt } + const requestConfig = { + headers: { + ...cloneDeep(headers?.headers || {}), + ...cloneDeep(configExtras?.headers || {}) + }, + params: { + ...cloneDeep(headers?.params || {}), + ...cloneDeep(configExtras?.params || {}) + } + } try { - const response = await http.post(url, httpBody, headers) + const response = await http.post(url, httpBody, requestConfig) if (response.data) { const data = response.data || {} if (http?.httpClientParams?.headers?.api_version) { diff --git a/lib/stack/contentType/entry/index.js b/lib/stack/contentType/entry/index.js index 0f82561f..2901986d 100644 --- a/lib/stack/contentType/entry/index.js +++ b/lib/stack/contentType/entry/index.js @@ -285,7 +285,8 @@ export function Entry (http, data) { * @description The variants call returns a Variants instance for managing variants of an entry. * @memberof Entry * @func variants - * @param {String=} uid - Variant UID. If not provided, returns Variants instance for querying all variants. + * @param {string|string[]=} variantUidOrUids - Variant UID, list of UIDs (comma-separated in the path), or omit to query all variants. + * @param {string=} branchName - Optional branch UID or alias for this variants scope (sent as the branch header). Omit to use the stack default branch. * @returns {Variants} Instance of Variants. * @example * import * as contentstack from '@contentstack/management' @@ -293,14 +294,51 @@ export function Entry (http, data) { * const variants = client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry('uid').variants('uid') * variants.fetch() * .then((response) => console.log(response)); + * @example + * client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry('uid').variants('uid', 'branch_name').update(data) + * .then((response) => console.log(response)); */ - this.variants = (uid = null) => { - const data = { stackHeaders: this.stackHeaders } - data.content_type_uid = this.content_type_uid - data.entry_uid = this.uid - if (uid) { - data.variants_uid = uid + this.variants = (variantUidOrUids, branchName) => { + const uidInput = variantUidOrUids === undefined ? null : variantUidOrUids + const branch = + typeof branchName === 'string' && branchName !== '' + ? branchName + : undefined + + const data = { + content_type_uid: this.content_type_uid, + entry_uid: this.uid + } + + if (branch === undefined) { + data.stackHeaders = this.stackHeaders + } else { + data.stackHeaders = { + ...cloneDeep(this.stackHeaders || {}), + branch + } } + + let variantsUid = null + if (Array.isArray(uidInput)) { + const uids = uidInput.filter( + (uid) => typeof uid === 'string' && uid.length > 0 + ) + if (uids.length === 1) { + variantsUid = uids[0] + } else if (uids.length > 1) { + variantsUid = uids.join(',') + } + } else if (typeof uidInput === 'string' && uidInput.length > 0) { + variantsUid = uidInput + } else if (uidInput != null && uidInput !== '') { + variantsUid = uidInput + } + + if (variantsUid != null && variantsUid !== '') { + data.variants_uid = variantsUid + } + return new Variants(http, data) } diff --git a/lib/stack/contentType/entry/variants/index.js b/lib/stack/contentType/entry/variants/index.js index 27f3f56f..c15a1968 100644 --- a/lib/stack/contentType/entry/variants/index.js +++ b/lib/stack/contentType/entry/variants/index.js @@ -2,7 +2,8 @@ import cloneDeep from 'lodash/cloneDeep' import { deleteEntity, fetch, - query + query, + publishUnpublish } from '../../../../entity' import error from '../../../../core/contentstackError' @@ -14,8 +15,19 @@ import { bindModuleHeaders } from '../../../../core/moduleHeaderSupport.js' export function Variants (http, data) { Object.assign(this, cloneDeep(data)) this.urlPath = `/content_types/${this.content_type_uid}/entries/${this.entry_uid}/variants` - if (data && data.variants_uid) { - this.urlPath += `/${this.variants_uid}` + let variantPathSegment = '' + if (data?.variants_uid != null && data.variants_uid !== '') { + if (Array.isArray(data.variants_uid)) { + variantPathSegment = data.variants_uid + .filter((uid) => typeof uid === 'string' && uid.length > 0) + .join(',') + } else { + variantPathSegment = String(data.variants_uid) + } + } + if (variantPathSegment) { + this.urlPath += `/${variantPathSegment}` + const entryBaseUrlPath = `/content_types/${this.content_type_uid}/entries/${this.entry_uid}` /** * @description The Update a variant call updates an existing variant for the selected content type. * @memberof Variants @@ -38,7 +50,7 @@ export function Variants (http, data) { * } * } * } - * client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry('entry_uid').variants('uid').update(data) + * client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry('entry_uid').variants('uid', 'branch_name').update(data) * .then((variants) => console.log(variants)) */ this.update = async (data, params = {}) => { @@ -121,6 +133,88 @@ export function Variants (http, data) { return error(err) } } + + /** + * @description Publishes via the entry publish endpoint (POST .../entries/{entry_uid}/publish). Pass `publishDetails` as the object nested under `entry` (environments, locales, variants, variant_rules, etc.). Optional `headers` and `params` are merged into the HTTP request. + * @memberof Variants + * @func publish + * @param {Object} options + * @param {Object} options.publishDetails - Payload for the `entry` property (e.g. environments, locales, variants, variant_rules). + * @param {String|null} [options.locale] - Top-level `locale` on the request body. + * @param {Number|null} [options.version] - Top-level `version` on the request body. + * @param {String|null} [options.scheduledAt] - Top-level `scheduled_at` (ISO) on the request body. + * @param {Object} [options.headers={}] - Extra request headers merged with stack headers. + * @param {Object} [options.params={}] - Query string parameters for the request. + * @returns {Promise} Response data (e.g. notice, job_id). + * @example + * import * as contentstack from '@contentstack/management' + * const client = contentstack.client() + * await client.stack({ api_key: 'api_key' }).contentType('ct').entry('entry_uid').variants('variant_uid').publish({ + * publishDetails: { + * environments: ['production'], + * locales: ['en-us'], + * variants: [{ uid: 'variant_uid', version: 1 }], + * variant_rules: { publish_latest_base: false, publish_latest_base_conditionally: true } + * }, + * locale: 'en-us' + * }) + */ + this.publish = async ({ + publishDetails, + locale = null, + version = null, + scheduledAt = null, + headers: extraHeaders = {}, + params = {} + }) => { + const url = `${entryBaseUrlPath}/publish` + const httpBody = {} + httpBody.entry = cloneDeep(publishDetails) + const baseHeaders = { + headers: { + ...cloneDeep(this.stackHeaders) + } + } + return publishUnpublish(http, url, httpBody, baseHeaders, locale, version, scheduledAt, { + headers: extraHeaders, + params + }) + } + + /** + * @description Unpublishes via the entry unpublish endpoint (POST .../entries/{entry_uid}/unpublish). Pass `publishDetails` as the object nested under `entry`. Optional `headers` and `params` are merged into the HTTP request. + * @memberof Variants + * @func unpublish + * @param {Object} options + * @param {Object} options.publishDetails - Payload for the `entry` property (e.g. environments, locales, variants). + * @param {String|null} [options.locale] - Top-level `locale` on the request body. + * @param {Number|null} [options.version] - Top-level `version` on the request body. + * @param {String|null} [options.scheduledAt] - Top-level `scheduled_at` (ISO) on the request body. + * @param {Object} [options.headers={}] - Extra request headers merged with stack headers. + * @param {Object} [options.params={}] - Query string parameters for the request. + * @returns {Promise} Response data (e.g. notice, job_id). + */ + this.unpublish = async ({ + publishDetails, + locale = null, + version = null, + scheduledAt = null, + headers: extraHeaders = {}, + params = {} + }) => { + const url = `${entryBaseUrlPath}/unpublish` + const httpBody = {} + httpBody.entry = cloneDeep(publishDetails) + const baseHeaders = { + headers: { + ...cloneDeep(this.stackHeaders) + } + } + return publishUnpublish(http, url, httpBody, baseHeaders, locale, version, scheduledAt, { + headers: extraHeaders, + params + }) + } } else { /** * @description The Query on Variants will allow you to fetch details of all or specific Variants. diff --git a/package-lock.json b/package-lock.json index 58923100..952daa3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentstack/management", - "version": "1.30.4", + "version": "1.31.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/management", - "version": "1.30.4", + "version": "1.31.0", "license": "MIT", "dependencies": { "@contentstack/utils": "^1.9.1", diff --git a/package.json b/package.json index 49e11d10..f4bd95b0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/management", - "version": "1.30.4", + "version": "1.31.0", "description": "The Content Management API is used to manage the content of your Contentstack account", "main": "./dist/node/contentstack-management.js", "browser": "./dist/web/contentstack-management.js", diff --git a/test/sanity-check/api/entryVariants-test.js b/test/sanity-check/api/entryVariants-test.js index 3b3d1194..e46d955c 100644 --- a/test/sanity-check/api/entryVariants-test.js +++ b/test/sanity-check/api/entryVariants-test.js @@ -259,6 +259,159 @@ describe('Entry Variants API Tests', () => { }) }) + /** + * SDK: .variants(variantUidOrUids, branchName?) — optional branch sent as the `branch` header + * for this variants scope (stack default branch when omitted). + * Uses `main` when the Branch API is available; skips if branches are not enabled on the stack. + */ + describe('Entry Variants with explicit branch (second argument)', () => { + let branchForVariants = null + + before(async function () { + this.timeout(30000) + try { + const mainBranch = await stack.branch('main').fetch() + if (mainBranch && mainBranch.uid) { + branchForVariants = mainBranch.uid + } + } catch (e) { + console.log(' Entry Variants branch tests: could not resolve main branch —', e.errorMessage || e.message) + branchForVariants = null + } + }) + + it('should fetch entry variant with variants(uid, branch)', async function () { + this.timeout(20000) + + if (!branchForVariants || !contentTypeUid || !entryUid || !variantUid) { + this.skip() + } + + try { + const response = await stack + .contentType(contentTypeUid) + .entry(entryUid) + .variants(variantUid, branchForVariants) + .fetch() + + trackedExpect(response, 'Entry variant fetch (with branch)').toBeAn('object') + trackedExpect(response.entry, 'Entry variant entry').toExist() + trackedExpect(response.entry._variant, 'Entry variant _variant').toExist() + } catch (error) { + if (error.status === 403 || error.status === 404 || error.status === 422) { + this.skip() + } + throw error + } + }) + + it('should update entry variant with variants(uid, branch)', async function () { + this.timeout(20000) + + if (!branchForVariants || !contentTypeUid || !entryUid || !variantUid) { + this.skip() + } + + const variantEntryData = { + entry: { + title: `Branch arg variant ${generateUniqueId()}`, + _variant: { + _change_set: ['title'] + } + } + } + + try { + const response = await stack + .contentType(contentTypeUid) + .entry(entryUid) + .variants(variantUid, branchForVariants) + .update(variantEntryData) + + trackedExpect(response, 'Entry variant update (with branch)').toBeAn('object') + trackedExpect(response.entry, 'Entry variant entry').toExist() + trackedExpect(response.entry.title, 'Entry variant title').toExist() + } catch (error) { + if (error.status === 403 || error.status === 422 || error.status === 412) { + this.skip() + } + throw error + } + }) + + it('should list entry variants with variants(null, branch).query().find()', async function () { + this.timeout(20000) + + if (!branchForVariants || !contentTypeUid || !entryUid) { + this.skip() + } + + try { + const response = await stack + .contentType(contentTypeUid) + .entry(entryUid) + .variants(null, branchForVariants) + .query({}) + .find() + + expect(response.items).to.be.an('array') + } catch (error) { + if (error.status === 403 || error.status === 404) { + this.skip() + } + throw error + } + }) + + it('should fetch variant versions with variants(uid, branch).versions()', async function () { + this.timeout(20000) + + if (!branchForVariants || !contentTypeUid || !entryUid || !variantUid) { + this.skip() + } + + try { + const response = await stack + .contentType(contentTypeUid) + .entry(entryUid) + .variants(variantUid, branchForVariants) + .versions() + + expect(response).to.be.an('object') + expect(response.versions).to.be.an('array') + } catch (error) { + if (error.status === 403 || error.status === 404 || error.status === 422) { + this.skip() + } + throw error + } + }) + + it('should fetch entry variant with variants([uid], branch) (single-element array)', async function () { + this.timeout(20000) + + if (!branchForVariants || !contentTypeUid || !entryUid || !variantUid) { + this.skip() + } + + try { + const response = await stack + .contentType(contentTypeUid) + .entry(entryUid) + .variants([variantUid], branchForVariants) + .fetch() + + trackedExpect(response.entry, 'Entry variant entry (array uid)').toExist() + trackedExpect(response.entry._variant, 'Entry variant _variant').toExist() + } catch (error) { + if (error.status === 403 || error.status === 404 || error.status === 422) { + this.skip() + } + throw error + } + }) + }) + describe('Entry Variant Publishing', () => { it('should publish entry variant', async function () { this.timeout(15000) @@ -299,6 +452,46 @@ describe('Entry Variants API Tests', () => { } }) + it('should publish entry variant via variants(uid).publish()', async function () { + this.timeout(15000) + + if (!contentTypeUid || !entryUid || !variantUid) { + this.skip() + } + + const publishDetails = { + environments: [environmentName], + locales: ['en-us'], + variants: [{ + uid: variantUid, + version: 1 + }], + variant_rules: { + publish_latest_base: false, + publish_latest_base_conditionally: true + } + } + + try { + const response = await stack + .contentType(contentTypeUid) + .entry(entryUid) + .variants(variantUid) + .publish({ + publishDetails, + locale: 'en-us' + }) + + expect(response.notice).to.not.equal(undefined) + } catch (error) { + if (error.status === 403 || error.status === 422) { + this.skip() + } else { + console.log('variants().publish warning:', error.message) + } + } + }) + it('should publish entry variant with api_version', async function () { this.timeout(15000) @@ -368,6 +561,42 @@ describe('Entry Variants API Tests', () => { } } }) + + it('should unpublish entry variant via variants(uid).unpublish()', async function () { + this.timeout(15000) + + if (!contentTypeUid || !entryUid || !variantUid) { + this.skip() + } + + const unpublishDetails = { + environments: [environmentName], + locales: ['en-us'], + variants: [{ + uid: variantUid, + version: 1 + }] + } + + try { + const response = await stack + .contentType(contentTypeUid) + .entry(entryUid) + .variants(variantUid) + .unpublish({ + publishDetails: unpublishDetails, + locale: 'en-us' + }) + + expect(response.notice).to.not.equal(undefined) + } catch (error) { + if (error.status === 403 || error.status === 422) { + this.skip() + } else { + console.log('variants().unpublish warning:', error.message) + } + } + }) }) describe('Entry Variant Deletion', () => { diff --git a/test/unit/variants-entry-test.js b/test/unit/variants-entry-test.js index 69589873..3688770e 100644 --- a/test/unit/variants-entry-test.js +++ b/test/unit/variants-entry-test.js @@ -238,6 +238,155 @@ describe('Contentstack Variants entry test', () => { }) .catch(done) }) + + it('Variants entry publish posts to entry publish URL with optional headers and params', (done) => { + const mock = new MockAdapter(Axios) + mock.onPost('/content_types/content_type_uid/entries/entry_uid/publish').reply((config) => { + const body = typeof config.data === 'string' ? JSON.parse(config.data) : config.data + expect(body.entry).to.be.an('object') + expect(body.entry.variants).to.be.an('array') + expect(body.entry.variants[0].uid).to.equal('variant_uid') + expect(body.locale).to.equal('en-us') + expect(config.headers['x-custom']).to.equal('1') + expect(config.params.t).to.equal('1') + return [200, { notice: 'Entry sent for publishing.', job_id: 'jid' }] + }) + makeEntryVariants({ + content_type_uid: 'content_type_uid', + entry_uid: 'entry_uid', + variants_uid: 'variant_uid', + stackHeaders: { api_key: 'k' } + }) + .publish({ + publishDetails: { + environments: ['development'], + locales: ['en-us'], + variants: [{ uid: 'variant_uid', version: 1 }], + variant_rules: { publish_latest_base_conditionally: true } + }, + locale: 'en-us', + headers: { 'x-custom': '1' }, + params: { t: '1' } + }) + .then((res) => { + expect(res.notice).to.include('publish') + done() + }) + .catch(done) + }) + + it('Variants entry unpublish posts to entry unpublish URL with optional headers and params', (done) => { + const mock = new MockAdapter(Axios) + mock.onPost('/content_types/content_type_uid/entries/entry_uid/unpublish').reply((config) => { + const body = typeof config.data === 'string' ? JSON.parse(config.data) : config.data + expect(body.entry).to.be.an('object') + expect(body.entry.variants).to.be.an('array') + expect(body.locale).to.equal('en-us') + expect(config.headers['x-unpub']).to.equal('y') + expect(config.params.q).to.equal('2') + return [200, { notice: 'Entry sent for unpublishing.' }] + }) + makeEntryVariants({ + content_type_uid: 'content_type_uid', + entry_uid: 'entry_uid', + variants_uid: 'variant_uid', + stackHeaders: { api_key: 'k' } + }) + .unpublish({ + publishDetails: { + environments: ['development'], + locales: ['en-us'], + variants: [{ uid: 'variant_uid', version: 1 }] + }, + locale: 'en-us', + headers: { 'x-unpub': 'y' }, + params: { q: '2' } + }) + .then((res) => { + expect(res.notice).to.include('unpublish') + done() + }) + .catch(done) + }) + + it('Entry variants fetch sends optional branch header', (done) => { + const mock = new MockAdapter(Axios) + mock + .onGet('/content_types/content_type_uid/entries/UID/variants/v1') + .reply((config) => { + expect(config.headers.branch).to.equal('feature_branch') + return [200, { + entry: { + ...varinatsEntryMock + } + }] + }) + makeEntry({ + entry: { ...systemUidMock }, + stackHeaders: { api_key: 'test_key' } + }) + .variants('v1', 'feature_branch') + .fetch() + .then((entry) => { + checkEntry(entry.entry) + done() + }) + .catch(done) + }) + + it('Entry variants multiple UIDs and branch on update', (done) => { + const mock = new MockAdapter(Axios) + mock + .onPut('/content_types/content_type_uid/entries/entry_uid/variants/u1,u2') + .reply((config) => { + expect(config.headers.branch).to.equal('devel') + return [200, { + entry: { + title: 'ok', + uid: 'variant_uid', + content_type: 'content_type_uid', + locale: 'en-us', + _version: 1, + _in_progress: false + } + }] + }) + makeEntry({ + entry: { ...systemUidMock, uid: 'entry_uid' }, + stackHeaders: { api_key: 'k' } + }) + .variants(['u1', 'u2'], 'devel') + .update({ entry: { title: 'x' } }) + .then((response) => { + expect(response.entry.title).to.be.equal('ok') + done() + }) + .catch(done) + }) + + it('Entry variants query mode with branch only', (done) => { + const mock = new MockAdapter(Axios) + mock + .onGet('/content_types/content_type_uid/entries/UID/variants') + .reply((config) => { + expect(config.headers.branch).to.equal('staging') + return [200, { + entries: [varinatsEntryMock] + }] + }) + makeEntry({ + entry: { ...systemUidMock }, + stackHeaders: { api_key: 'k' } + }) + .variants(null, 'staging') + .query() + .find() + .then((collection) => { + checkEntry(collection.items[0].variants) + done() + }) + .catch(done) + }) }) function makeEntryVariants (data) { diff --git a/types/stack/contentType/entry.d.ts b/types/stack/contentType/entry.d.ts index 71b7c214..4a33a465 100644 --- a/types/stack/contentType/entry.d.ts +++ b/types/stack/contentType/entry.d.ts @@ -8,7 +8,7 @@ import { Variants, Variant } from "./variants"; export interface Entry extends Publishable, Unpublishable, SystemFields, SystemFunction { variants(): Variants - variants(uid: string): Variant + variants(variantUidOrUids: string | string[], branchName?: string): Variant setWorkflowStage(data: { workflow_stage: WorkflowStage, locale?:string}): Promise locales(): Promise references(param: object): Promise diff --git a/types/stack/contentType/variants.d.ts b/types/stack/contentType/variants.d.ts index b584785f..da8f973f 100644 --- a/types/stack/contentType/variants.d.ts +++ b/types/stack/contentType/variants.d.ts @@ -2,7 +2,21 @@ import { Response } from "../../contentstackCollection"; import { AnyProperty, SystemFields } from "../../utility/fields"; import { Queryable, SystemFunction } from "../../utility/operations"; +/** Options for {@link Variant.publish} and {@link Variant.unpublish} (entry publish/unpublish APIs with variant payload). */ +export interface VariantPublishUnpublishOptions { + publishDetails: AnyProperty + locale?: string | null + version?: number | null + scheduledAt?: string | null + /** Merged with stack headers on the request */ + headers?: Record + /** Query string parameters */ + params?: Record +} + export interface Variant extends SystemFields, SystemFunction { + publish(options: VariantPublishUnpublishOptions): Promise + unpublish(options: VariantPublishUnpublishOptions): Promise } export interface Variants extends Queryable { } diff --git a/types/utility/publish.d.ts b/types/utility/publish.d.ts index 4cc63427..68085f38 100644 --- a/types/utility/publish.d.ts +++ b/types/utility/publish.d.ts @@ -11,6 +11,10 @@ export interface PublishConfig { locale?: string version?: number scheduledAt?: string + /** Extra HTTP headers merged with stack headers (publish / unpublish). */ + headers?: Record + /** Query string parameters (publish / unpublish). */ + params?: Record } export interface Publishable {