diff --git a/CHANGELOG.md b/CHANGELOG.md index b65b5e61..84e015bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [v1.20.2](https://github.com/contentstack/contentstack-management-javascript/tree/v1.20.2) (2025-04-21) - Fix - Handle the sanity tests when ENVs are not provided + - Handle api_version chaining and ensure backward compatibility ## [v1.20.1](https://github.com/contentstack/contentstack-management-javascript/tree/v1.20.1) (2025-04-07) - Fix - Ensure 'api' is replaced with 'app' in uiHostName regardless of position diff --git a/lib/entity.js b/lib/entity.js index bece8aba..6fcb22ff 100644 --- a/lib/entity.js +++ b/lib/entity.js @@ -45,6 +45,12 @@ export const publishUnpublish = async (http, url, httpBody, headers, locale = nu const response = await http.post(url, httpBody, headers) if (response.data) { const data = response.data || {} + if (http?.httpClientParams?.headers?.api_version) { + delete http.httpClientParams.headers.api_version + } + if (headers?.api_version) { + delete headers.api_version + } if (headers) { data.stackHeaders = headers } @@ -82,8 +88,7 @@ export const upload = async ({ http, urlPath, stackHeaders, formData, params, me export const create = ({ http, params }) => { return async function (data, param) { this.stackHeaders = { - ...this.stackHeaders, - ...(http.httpClientParams.headers?.api_version && { api_version: http.httpClientParams.headers.api_version }) + ...this.stackHeaders } const headers = { headers: { @@ -259,6 +264,9 @@ export const fetchAll = (http, wrapperCollection, params = {}) => { export function parseData (response, stackHeaders, contentTypeUID, taxonomyUid, http) { const data = response.data || {} + if (stackHeaders && 'api_version' in stackHeaders) { + delete stackHeaders.api_version + } if (stackHeaders) { data.stackHeaders = stackHeaders } diff --git a/lib/stack/globalField/index.js b/lib/stack/globalField/index.js index 3f36cc82..32c14838 100644 --- a/lib/stack/globalField/index.js +++ b/lib/stack/globalField/index.js @@ -1,5 +1,5 @@ import cloneDeep from 'lodash/cloneDeep' -import { query, upload, parseData } from '../../entity' +import { create, update, deleteEntity, fetch, query, upload, parseData } from '../../entity' import error from '../../core/contentstackError' import FormData from 'form-data' import { createReadStream } from 'fs' @@ -11,10 +11,8 @@ import { createReadStream } from 'fs' export function GlobalField (http, data = {}) { this.stackHeaders = data.stackHeaders - this.apiVersion = data.api_version || undefined - - if (this.apiVersion) { - this.stackHeaders.api_version = this.apiVersion + if (data.api_version) { + this.stackHeaders.api_version = data.api_version } this.urlPath = `/global_fields` @@ -39,89 +37,7 @@ export function GlobalField (http, data = {}) { * .then((globalField) => console.log(globalField)) * */ - this.update = async (config) => { - try { - // Add `api_version` to headers if `this.apiVersion` is defined - if (this.apiVersion) { - this.stackHeaders.api_version = this.apiVersion - } - const headers = { - headers: { - ...cloneDeep(this.stackHeaders) - } - } - const response = await http.put(`${this.urlPath}`, config, headers) - // Remove `api_version` from headers after fetching data - if (this.apiVersion) { - delete this.stackHeaders.api_version - } - const data = response.data - if (data) { - if (this.stackHeaders) { - data.stackHeaders = this.stackHeaders - } - return data - } else { - throw error(response) - } - } catch (err) { - throw error(err) - } - } - - /** - * @description The Update GlobalField call lets you update the name and description of an existing GlobalField. - * @memberof GlobalField - * @func update - * @returns {Promise} Promise for GlobalField instance - * @example - * import * as contentstack from '@contentstack/management' - * const client = contentstack.client() - * const data = { - * "global_field": { - * "title": "Nested Global Field33", - * "uid": "nested_global_field33", - * "schema": [ - * { - * "data_type": "text", - * "display_name": "Single Line Textbox", - * "uid": "single_line" - * }, - * { - * "data_type": "global_field", - * "display_name": "Global", - * "uid": "global_field", - * "reference_to": "nested_global_field_123" - * } - * ] - * } - * } - * client.stack({ api_key: 'api_key'}).globalField('global_field_uid').updateNestedGlobalField(data, { headers: { api_version: '3.2' }}) - * .then((globalField) => { - console.log(globalField) - * }) - */ - this.updateNestedGlobalField = async (config, headers = {}) => { - const apiVersion = { api_version: '3.2' } - this.stackHeaders = { ...this.stackHeaders, ...apiVersion, ...headers } - try { - const headers = { - headers: { ...cloneDeep(this.stackHeaders) } - } - const response = await http.put(`${this.urlPath}`, config, headers) - const data = response.data - if (data) { - if (this.stackHeaders) { - data.stackHeaders = this.stackHeaders - } - return data - } else { - throw error(response) - } - } catch (err) { - throw error(err) - } - } + this.update = update(http, 'global_field') /** * @description The Delete GlobalField call is used to delete an existing GlobalField permanently from your Stack. @@ -135,38 +51,7 @@ export function GlobalField (http, data = {}) { * client.stack({ api_key: 'api_key'}).globalField('global_field_uid').delete() * .then((response) => console.log(response.notice)) */ - this.delete = async () => { - const param = {} - try { - // Add `api_version` to headers if `this.apiVersion` is defined - if (this.apiVersion) { - this.stackHeaders.api_version = this.apiVersion - } - const headers = { - headers: { - ...cloneDeep(this.stackHeaders) - }, - params: { - ...cloneDeep(param) - } - } - const response = await http.delete(this.urlPath, headers) - if (this.apiVersion) { - delete this.stackHeaders.api_version - } - const data = response.data - if (data) { - if (this.stackHeaders) { - data.stackHeaders = this.stackHeaders - } - return data - } else { - throw error(response) - } - } catch (err) { - throw error(err) - } - } + this.delete = deleteEntity(http) /** * @description The fetch GlobalField call fetches GlobalField details. @@ -181,33 +66,7 @@ export function GlobalField (http, data = {}) { * .then((globalField) => console.log(globalField)) * */ - this.fetch = async function (param = {}) { - try { - if (this.apiVersion) { - this.stackHeaders.api_version = this.apiVersion - } - const headers = { - headers: { - ...cloneDeep(this.stackHeaders) - }, - params: { - ...cloneDeep(param) - } - } - const response = await http.get(this.urlPath, headers) - const data = response.data - if (data) { - if (this.stackHeaders) { - data.stackHeaders = this.stackHeaders - } - return data - } else { - throw error(response) - } - } catch (err) { - throw error(err) - } - } + this.fetch = fetch(http, 'global_field') } else { /** * @description The Create a GlobalField call creates a new globalField in a particular stack of your Contentstack account. @@ -230,30 +89,7 @@ export function GlobalField (http, data = {}) { * client.stack().globalField().create({ global_field }) * .then((globalField) => console.log(globalField)) */ - this.create = async (payload) => { - try { - if (this.apiVersion) { - this.stackHeaders.api_version = this.apiVersion - } - const headers = { - headers: { - ...cloneDeep(this.stackHeaders) - } - } - const response = await http.post(`${this.urlPath}`, payload, headers) - const data = response.data - if (data) { - if (this.stackHeaders) { - data.stackHeaders = this.stackHeaders - } - return data - } else { - throw error(response) - } - } catch (err) { - return error(err) - } - } + this.create = create({ http: http }) /** * @description The Query on GlobalField will allow to fetch details of all or specific GlobalField diff --git a/lib/stack/index.js b/lib/stack/index.js index 74416687..3ced19ee 100644 --- a/lib/stack/index.js +++ b/lib/stack/index.js @@ -164,25 +164,16 @@ export function Stack (http, data) { * .then((globalField) => console.log(globalField)) * */ - this.globalField = (globalFieldUidOrOptions = null, options = {}) => { + // eslint-disable-next-line camelcase + this.globalField = (globalFieldUid = null, api_version = '3.0') => { const data = { - stackHeaders: this.stackHeaders + stackHeaders: this.stackHeaders, + // eslint-disable-next-line camelcase + api_version: api_version } - if (typeof globalFieldUidOrOptions === 'object' && globalFieldUidOrOptions !== null) { - options = globalFieldUidOrOptions - } else if (globalFieldUidOrOptions) { - data.global_field = { uid: globalFieldUidOrOptions } + if (globalFieldUid) { + data.global_field = { uid: globalFieldUid } } - - // Safely handle `options` and check for `api_version` - options = options || {} // Ensure `options` is always an object - if (options && typeof options === 'object' && options.api_version) { - data.api_version = options.api_version - if (options.api_version === '3.2') { - data.nested_global_fields = true - } - } - return new GlobalField(http, data) } diff --git a/test/sanity-check/api/globalfield-test.js b/test/sanity-check/api/globalfield-test.js index 789224fc..eb5ad12a 100644 --- a/test/sanity-check/api/globalfield-test.js +++ b/test/sanity-check/api/globalfield-test.js @@ -1,5 +1,6 @@ import path from 'path' import { expect } from 'chai' +import { cloneDeep } from 'lodash' import { describe, it, setup } from 'mocha' import { jsonReader } from '../utility/fileOperations/readwrite' import { createGlobalField } from '../mock/globalfield' @@ -19,7 +20,6 @@ describe('Global Field api Test', () => { makeGlobalField() .create(createGlobalField) .then((globalField) => { - globalField = globalField.global_field expect(globalField.uid).to.be.equal(createGlobalField.global_field.uid) expect(globalField.title).to.be.equal( createGlobalField.global_field.title @@ -42,7 +42,6 @@ describe('Global Field api Test', () => { makeGlobalField(createGlobalField.global_field.uid) .fetch() .then((globalField) => { - globalField = globalField.global_field expect(globalField.uid).to.be.equal(createGlobalField.global_field.uid) expect(globalField.title).to.be.equal( createGlobalField.global_field.title @@ -61,26 +60,16 @@ describe('Global Field api Test', () => { .catch(done) }) - it('should update global Field', (done) => { - makeGlobalField(createGlobalField.global_field.uid) - .update(createGlobalField) + it('should update global Field', done => { + const globalField = makeGlobalField(createGlobalField.global_field.uid) + Object.assign(globalField, cloneDeep(createGlobalField.global_field)) + globalField.update() .then((updateGlobal) => { - updateGlobal = updateGlobal.global_field - expect(updateGlobal.uid).to.be.equal( - createGlobalField.global_field.uid - ) - expect(updateGlobal.title).to.be.equal( - createGlobalField.global_field.title - ) - expect(updateGlobal.schema[0].uid).to.be.equal( - createGlobalField.global_field.schema[0].uid - ) - expect(updateGlobal.schema[0].data_type).to.be.equal( - createGlobalField.global_field.schema[0].data_type - ) - expect(updateGlobal.schema[0].display_name).to.be.equal( - createGlobalField.global_field.schema[0].display_name - ) + expect(updateGlobal.uid).to.be.equal(createGlobalField.global_field.uid) + expect(updateGlobal.title).to.be.equal(createGlobalField.global_field.title) + expect(updateGlobal.schema[0].uid).to.be.equal(createGlobalField.global_field.schema[0].uid) + expect(updateGlobal.schema[0].data_type).to.be.equal(createGlobalField.global_field.schema[0].data_type) + expect(updateGlobal.schema[0].display_name).to.be.equal(createGlobalField.global_field.schema[0].display_name) done() }) .catch(done) @@ -145,7 +134,7 @@ describe('Global Field api Test', () => { // it('should create nested global field for reference', done => { // makeGlobalField({ api_version: '3.2' }).create(createNestedGlobalFieldForReference) // .then(globalField => { - // expect(globalField.global_field.uid).to.be.equal(createNestedGlobalFieldForReference.global_field.uid); + // expect(globalField.uid).to.be.equal(createNestedGlobalFieldForReference.global_field.uid); // done(); // }) // .catch(err => { @@ -157,7 +146,7 @@ describe('Global Field api Test', () => { // it('should create nested global field', done => { // makeGlobalField({ api_version: '3.2' }).create(createNestedGlobalField) // .then(globalField => { - // expect(globalField.global_field.uid).to.be.equal(createNestedGlobalField.global_field.uid); + // expect(globalField.uid).to.be.equal(createNestedGlobalField.global_field.uid); // done(); // }) // .catch(err => { @@ -169,7 +158,7 @@ describe('Global Field api Test', () => { // it('should fetch nested global field', done => { // makeGlobalField(createNestedGlobalField.global_field.uid, { api_version: '3.2' }).fetch() // .then(globalField => { - // expect(globalField.global_field.uid).to.be.equal(createNestedGlobalField.global_field.uid); + // expect(globalField.uid).to.be.equal(createNestedGlobalField.global_field.uid); // done(); // }) // .catch(err => { @@ -178,11 +167,33 @@ describe('Global Field api Test', () => { // }); // }); - // it('should update nested global fields without fetch', done => { - // makeGlobalField(createNestedGlobalField.global_field.uid, { api_version: '3.2' }) - // .update(createNestedGlobalField) + // it('should fetch and update nested global Field', done => { + // makeGlobalField(createGlobalField.global_field.uid, { api_version: '3.2' }).fetch() // .then((globalField) => { - // expect(globalField.global_field.schema.length).to.be.equal(2) + // globalField.title = 'Update title' + // return globalField.update() + // }) + // .then((updateGlobal) => { + // expect(updateGlobal.uid).to.be.equal(createGlobalField.global_field.uid) + // expect(updateGlobal.title).to.be.equal('Update title') + // expect(updateGlobal.schema[0].uid).to.be.equal(createGlobalField.global_field.schema[0].uid) + // expect(updateGlobal.schema[0].data_type).to.be.equal(createGlobalField.global_field.schema[0].data_type) + // expect(updateGlobal.schema[0].display_name).to.be.equal(createGlobalField.global_field.schema[0].display_name) + // done() + // }) + // .catch(done) + // }) + + // it('should update nested global Field', done => { + // const globalField = makeGlobalField(createGlobalField.global_field.uid, { api_version: '3.2' }) + // Object.assign(globalField, cloneDeep(createGlobalField.global_field)) + // globalField.update() + // .then((updateGlobal) => { + // expect(updateGlobal.uid).to.be.equal(createGlobalField.global_field.uid) + // expect(updateGlobal.title).to.be.equal(createGlobalField.global_field.title) + // expect(updateGlobal.schema[0].uid).to.be.equal(createGlobalField.global_field.schema[0].uid) + // expect(updateGlobal.schema[0].data_type).to.be.equal(createGlobalField.global_field.schema[0].data_type) + // expect(updateGlobal.schema[0].display_name).to.be.equal(createGlobalField.global_field.schema[0].display_name) // done() // }) // .catch(done) diff --git a/test/unit/globalField-test.js b/test/unit/globalField-test.js index 361fbb60..8edaefa6 100644 --- a/test/unit/globalField-test.js +++ b/test/unit/globalField-test.js @@ -3,7 +3,7 @@ import Axios from 'axios' import { expect } from 'chai' import { describe, it } from 'mocha' import { GlobalField, GlobalFieldCollection, createFormData } from '../../lib/stack/globalField' -import { systemUidMock, checkSystemFields, globalFieldMock, stackHeadersMock, noticeMock, nestedGlobalFieldMock, nestedGlobalFieldPayload } from './mock/objects' +import { systemUidMock, checkSystemFields, globalFieldMock, stackHeadersMock, noticeMock, nestedGlobalFieldMock } from './mock/objects' import MockAdapter from 'axios-mock-adapter' describe('Contentstack GlobalField test', () => { @@ -84,7 +84,7 @@ describe('Contentstack GlobalField test', () => { makeGlobalField() .create() .then((globalField) => { - checkGlobalField(globalField.global_field) + checkGlobalField(globalField) done() }) .catch(done) @@ -120,7 +120,7 @@ describe('Contentstack GlobalField test', () => { }) .update() .then((globalField) => { - checkGlobalField(globalField.global_field) + checkGlobalField(globalField) done() }) .catch(done) @@ -141,7 +141,7 @@ describe('Contentstack GlobalField test', () => { }) .fetch() .then((globalField) => { - checkGlobalField(globalField.global_field) + checkGlobalField(globalField) done() }) .catch(done) @@ -221,7 +221,7 @@ describe('Contentstack GlobalField test (API Version 3.2)', () => { stackHeaders: stackHeadersMock, api_version: '3.2' }) expect(globalField.urlPath).to.be.equal('/global_fields') - expect(globalField.apiVersion).to.be.equal('3.2') + expect(globalField.stackHeaders.api_version).to.be.equal('3.2') expect(globalField.stackHeaders).to.deep.equal({ api_key: 'api_key', api_version: '3.2' }) done() }) @@ -237,7 +237,7 @@ describe('Contentstack GlobalField test (API Version 3.2)', () => { expect(globalField.urlPath).to.be.equal( `/global_fields/${systemUidMock.uid}` ) - expect(globalField.apiVersion).to.be.equal('3.2') + expect(globalField.stackHeaders.api_version).to.be.equal('3.2') expect(globalField.update).to.not.equal(undefined) expect(globalField.delete).to.not.equal(undefined) expect(globalField.fetch).to.not.equal(undefined) @@ -257,7 +257,7 @@ describe('Contentstack GlobalField test (API Version 3.2)', () => { expect(globalField.urlPath).to.be.equal( `/global_fields/${systemUidMock.uid}` ) - expect(globalField.apiVersion).to.be.equal('3.2') + expect(globalField.stackHeaders.api_version).to.be.equal('3.2') expect(globalField.stackHeaders).to.not.equal(undefined) expect(globalField.stackHeaders.api_key).to.be.equal( stackHeadersMock.api_key @@ -300,7 +300,7 @@ describe('Contentstack GlobalField test (API Version 3.2)', () => { api_version: '3.2' }) .create() .then((globalField) => { - checkGlobalField(globalField.global_field) + checkGlobalField(globalField) done() }) .catch(done) @@ -339,7 +339,7 @@ describe('Contentstack GlobalField test (API Version 3.2)', () => { }) .update() .then((globalField) => { - checkGlobalField(globalField.global_field) + checkGlobalField(globalField) done() }) .catch(done) @@ -361,7 +361,7 @@ describe('Contentstack GlobalField test (API Version 3.2)', () => { }) .fetch() .then((globalField) => { - checkGlobalField(globalField.global_field) + checkGlobalField(globalField) done() }) .catch(done) @@ -438,39 +438,6 @@ describe('Contentstack GlobalField test (API Version 3.2)', () => { }) .catch(done) }) - - it('should update nested global field', (done) => { - var mock = new MockAdapter(Axios) - const updatedData = { - global_field: { - title: 'Updated Nested Global Field Title', - schema: nestedGlobalFieldPayload - } - } - - mock - .onPut(`/global_fields/${systemUidMock.uid}`) - .reply(200, { - global_field: { - ...nestedGlobalFieldMock, - ...updatedData.global_field - } - }) - - makeGlobalField({ - global_field: { - ...systemUidMock - }, - stackHeaders: stackHeadersMock - }) - .updateNestedGlobalField(updatedData) - .then((response) => { - expect(response.global_field.title).to.be.equal('Updated Nested Global Field Title') - expect(response.global_field.schema).to.deep.equal(nestedGlobalFieldPayload) - done() - }) - .catch(done) - }) }) function makeGlobalField (data) {