import cloneDeep from 'lodash/cloneDeep'
import {
update,
deleteEntity,
fetch,
query,
parseData,
upload,
publish,
unpublish } from '../../entity'
import { Folder } from './folders'
import error from '../../core/contentstackError'
import FormData from 'form-data'
import { createReadStream } from 'fs'
/**
* Assets refer to all the media files (images, videos, PDFs, audio files, and so on) uploaded in your Contentstack repository for future use.
* These files can be attached and used in multiple entries. Read more about <a href='https://www.contentstack.com/docs/guide/content-management'>Assets</a>.
* @namespace Asset
*/
export function Asset (http, data = {}) {
this.stackHeaders = data.stackHeaders
this.urlPath = `/assets`
if (data.asset) {
Object.assign(this, cloneDeep(data.asset))
this.urlPath = `/assets/${this.uid}`
/**
* @description The Update Asset call lets you update the name and description of an existing Asset.
* @memberof Asset
* @func update
* @returns {Promise<Asset.Asset>} Promise for Asset instance
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack({ api_key: 'api_key'}).asset('uid').fetch()
* .then((asset) => {
* asset.title = 'My New asset'
* asset.description = 'Asset description'
* return asset.update()
* })
* .then((asset) => console.log(asset))
*
*/
this.update = update(http, 'asset')
/**
* @description The Delete asset call will delete an existing asset from the stack.
* @memberof Asset
* @func delete
* @returns {Object} Response Object.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack({ api_key: 'api_key'}).asset('uid').delete()
* .then((response) => console.log(response.notice))
*/
this.delete = deleteEntity(http)
/**
* @description The fetch an asset call returns comprehensive information about a specific version of an asset of a stack.
* @memberof Asset
* @func fetch
* @returns {Promise<Asset.Asset>} Promise for Asset instance
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack({ api_key: 'api_key'}).asset('uid').fetch()
* .then((asset) => console.log(asset))
*
*/
this.fetch = fetch(http, 'asset')
/**
* @description The Replace asset call will replace an existing asset with another file on the stack.
* @memberof Asset
* @func replace
* @returns {Promise<Asset.Asset>} Promise for Asset instance
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* const asset = {
* upload: 'path/to/file.png',
* }
*
* client.stack({ api_key: 'api_key'}).asset('uid').replace(asset)
* .then((asset) => console.log(asset))
*
*/
this.replace = async function (data, params) {
try {
const response = await upload({ http: http, urlPath: this.urlPath, stackHeaders: this.stackHeaders, formData: createFormData(data), params: params, method: 'PUT' })
if (response.data) {
return new this.constructor(http, parseData(response, this.stackHeaders))
} else {
throw error(response)
}
} catch (err) {
throw error(err)
}
}
/**
* @description The Publish an asset call is used to publish a specific version of an asset on the desired environment either immediately or at a later date/time.
* @memberof Asset
* @func publish
* @returns {Promise<Object>} Response Object.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* const asset = {
* "locales": [
* "en-us"
* ],
* "environments": [
* "development"
* ]
* }
*
* client.stack({ api_key: 'api_key'}).asset('uid').publish({ publishDetails: asset, version: 1, scheduledAt: "2019-02-08T18:30:00.000Z"})
* .then((response) => console.log(response.notice))
*
*/
this.publish = publish(http, 'asset')
/**
* @description The Replace asset call will replace an existing asset with another file on the stack.
* @memberof Asset
* @func unpublish
* @returns {Promise<Object>} Response Object.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* const asset = {
* "locales": [
* "en-us"
* ],
* "environments": [
* "development"
* ]
* }
*
* client.stack({ api_key: 'api_key'}).asset('uid').unpublish({ publishDetails: asset, version: 1, scheduledAt: "2019-02-08T18:30:00.000Z"})
* .then((response) => console.log(response.notice))
*
*/
this.unpublish = unpublish(http, 'asset')
} else {
/**
* @description The Folder allows to fetch and create folders in assets.
* @memberof Asset
* @func folder
* @returns {Promise<Folder.Folder>} Promise for Entry instance
*
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
* const asset = {name: 'My New contentType'}
* client.stack({ api_key: 'api_key'}).asset('uid').folder().create({ asset })
* .then((folder) => console.log(folder))
*/
this.folder = (folderUid = null) => {
const data = { stackHeaders: this.stackHeaders }
if (folderUid) {
data.asset = { uid: folderUid }
}
return new Folder(http, data)
}
/**
* @description The Create an asset call creates a new asset.
* @memberof Asset
* @func create
* @returns {Promise<Asset.Asset>} Promise for Asset instance
*
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* const asset = {
* upload: 'path/to/file.png',
* title: 'Title',
* description: 'Desc'
* }
*
* client.stack({ api_key: 'api_key'}).asset().create(asset)
* .then((asset) => console.log(asset))
*/
this.create = async function (data, params) {
try {
const response = await upload({ http: http, urlPath: this.urlPath, stackHeaders: this.stackHeaders, formData: createFormData(data), params: params })
if (response.data) {
return new this.constructor(http, parseData(response, this.stackHeaders))
} else {
throw error(response)
}
} catch (err) {
throw error(err)
}
}
/**
* @description The Query on Asset will allow to fetch details of all or specific Asset.
* @memberof Asset
* @param {Object} params - URI parameters
* @prop {Object} params.query - Queries that you can use to fetch filtered results.
* @func query
* @returns {Array<Asset>} Array of Asset.
*
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack({ api_key: 'api_key'}).asset().query({ query: { filename: 'Asset Name' } }).find()
* .then((asset) => console.log(asset))
*/
this.query = query({ http: http, wrapperCollection: AssetCollection })
}
/**
* @description The Download function will get downloadable file in specified format.
* @memberof Asset
* @func download
* @returns {Array<AssetResponse>} Array of Asset.
* @param {*} param.url The url for the asset to download
* @param {*} param.responseType Optional parameter to specify the response type.
* @example
*
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack({ api_key: 'api_key'}).asset('uid').fetch()
* .then((asset) => asset.download({responseType: 'blob'}))
* .then((response) => // Write response data to destination file. )
* @example
*
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack({ api_key: 'api_key'}).asset().download({url: 'asset_url_to_download', responseType: 'blob'})
* .then((response) => // Write response data to destination file. )
*/
this.download = async function ({ url, responseType, params }) {
try {
const headers = {
headers: {
...params,
...cloneDeep(this.stackHeaders)
},
responseType
} || { responseType }
const requestUrl = url || this.url
if (!requestUrl || requestUrl === undefined) {
throw new Error('Asset URL can not be empty')
}
return http.get(requestUrl, headers)
} catch (err) {
throw error(err)
}
}
return this
}
export function AssetCollection (http, data) {
const obj = cloneDeep(data.assets) || []
const assetCollection = obj.map((userdata) => {
return new Asset(http, { asset: userdata, stackHeaders: data.stackHeaders })
})
return assetCollection
}
export function createFormData (data) {
return () => {
const formData = new FormData()
if (typeof data['parent_uid'] === 'string') {
formData.append('asset[parent_uid]', data['parent_uid'])
}
if (typeof data.description === 'string') {
formData.append('asset[description]', data.description)
}
if (data.tags instanceof Array) {
formData.append('asset[tags]', data.tags.join(','))
} else if (typeof data.tags === 'string') {
formData.append('asset[tags]', data.tags)
}
if (typeof data.title === 'string') {
formData.append('asset[title]', data.title)
}
const uploadStream = createReadStream(data.upload)
formData.append('asset[upload]', uploadStream)
return formData
}
}