diff --git a/CHANGELOG.md b/CHANGELOG.md index 08500cf7..d7b701b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## [v1.19.6](https://github.com/contentstack/contentstack-management-javascript/tree/v1.19.6) (2025-03-31) + - Enhancement + - Added buffer upload in assets + ## [v1.19.5](https://github.com/contentstack/contentstack-management-javascript/tree/v1.19.5) (2025-03-17) - Fix - Added AuditLog in the stack class diff --git a/lib/stack/asset/index.js b/lib/stack/asset/index.js index 0d1a27e5..22e7757c 100644 --- a/lib/stack/asset/index.js +++ b/lib/stack/asset/index.js @@ -291,11 +291,21 @@ export function createFormData (data) { if (typeof data.title === 'string') { formData.append('asset[title]', data.title) } - const uploadStream = createReadStream(data.upload) - if (typeof data.content_type === 'string') { - formData.append('asset[upload]', uploadStream, { contentType: data.content_type }) + // Handle Buffer Upload + if (Buffer.isBuffer(data.upload)) { + formData.append('asset[upload]', data.upload, { + filename: data.filename || 'uploaded_file', + contentType: data.content_type || 'application/octet-stream' + }) + } else if (typeof data.upload === 'string') { // Handle File Path Upload + const uploadStream = createReadStream(data.upload) + if (typeof data.content_type === 'string') { + formData.append('asset[upload]', uploadStream, { contentType: data.content_type }) + } else { + formData.append('asset[upload]', uploadStream) + } } else { - formData.append('asset[upload]', uploadStream) + throw new Error('Invalid upload format. Must be a file path or Buffer.') } return formData } diff --git a/package-lock.json b/package-lock.json index 4f66bd64..27c8a5ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.19.5", "license": "MIT", "dependencies": { - "axios": "^1.8.2", + "axios": "^1.8.3", "form-data": "^4.0.2", "lodash": "^4.17.21", "qs": "^6.14.0" @@ -3681,7 +3681,9 @@ } }, "node_modules/axios": { - "version": "1.8.2", + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", diff --git a/package.json b/package.json index 691d9447..2895cf97 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "author": "Contentstack", "license": "MIT", "dependencies": { - "axios": "^1.8.2", + "axios": "^1.8.3", "form-data": "^4.0.2", "lodash": "^4.17.21", "qs": "^6.14.0" diff --git a/test/sanity-check/api/asset-test.js b/test/sanity-check/api/asset-test.js index 4aadb5be..72cb6cdf 100644 --- a/test/sanity-check/api/asset-test.js +++ b/test/sanity-check/api/asset-test.js @@ -1,3 +1,4 @@ +import fs from 'fs' import path from 'path' import { expect } from 'chai' import { describe, it, setup } from 'mocha' @@ -39,6 +40,31 @@ describe('Assets api Test', () => { .catch(done) }) + it('should upload asset from buffer', (done) => { + const filePath = path.join(__dirname, '../mock/customUpload.html') + const fileBuffer = fs.readFileSync(filePath) // Read file into Buffer + const asset = { + upload: fileBuffer, // Buffer upload + filename: 'customUpload.html', // Ensure filename is provided + content_type: 'text/html', // Set content type + title: 'buffer-asset', + description: 'Buffer Asset Desc', + tags: ['Buffer'] + } + makeAsset().create(asset) + .then((asset) => { + jsonWrite(asset, 'bufferAsset.json') + expect(asset.uid).to.be.not.equal(null) + expect(asset.url).to.be.not.equal(null) + expect(asset.filename).to.be.equal('customUpload.html') + expect(asset.title).to.be.equal('buffer-asset') + expect(asset.description).to.be.equal('Buffer Asset Desc') + expect(asset.content_type).to.be.equal('text/html') + done() + }) + .catch(done) + }) + it('should download asset from URL.', done => { makeAsset().download({ url: assetURL, responseType: 'stream' }) .then((response) => { diff --git a/test/unit/asset-test.js b/test/unit/asset-test.js index 24926889..bf4cb3b3 100644 --- a/test/unit/asset-test.js +++ b/test/unit/asset-test.js @@ -1,3 +1,4 @@ +import fs from 'fs' import path from 'path' import Axios from 'axios' import { expect } from 'chai' @@ -171,6 +172,49 @@ describe('Contentstack Asset test', () => { .catch(done) }) + it('should upload asset from buffer', (done) => { + const mock = new MockAdapter(Axios) + mock.onPost('/assets').reply(200, { + asset: { + uid: 'mock-uid', + url: '/assets', + filename: 'customUpload.html', + title: 'buffer-asset', + description: 'Buffer Asset Desc', + content_type: 'text/html', + tags: ['Buffer'], + parent_uid: 'UID' + } + }) + const filePath = path.join(__dirname, '../api/mock/customUpload.html') + const fileBuffer = fs.readFileSync(filePath) + const assetUpload = { + upload: fileBuffer, // Buffer upload + filename: 'customUpload.html', // Filename to identify the file + content_type: 'text/html', // MIME type + title: 'buffer-asset', + description: 'Buffer Asset Desc', + tags: ['Buffer'], + parent_uid: 'UID' + } + const form = createFormData(assetUpload)() // Create FormData for Buffer upload + const boundary = form.getBoundary() + expect(boundary).to.be.equal(form.getBoundary()) + expect(boundary.length).to.be.greaterThan(30) + makeAsset() + .create(assetUpload) + .then((asset) => { + expect(asset.uid).to.be.equal('mock-uid') + expect(asset.filename).to.be.equal('customUpload.html') + expect(asset.title).to.be.equal('buffer-asset') + expect(asset.description).to.be.equal('Buffer Asset Desc') + expect(asset.content_type).to.be.equal('text/html') + expect(asset.tags).to.include('Buffer') + done() + }) + .catch(done) + }) + it('Asset replace test', done => { var mock = new MockAdapter(Axios) mock.onPut('/assets/UID').reply(200, {