Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# This workflow will publish a package to GitHub Packages when a release is created
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages

name: Publish package to NPM repository
on:
release:
types: [created]

jobs:
publish-npm:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '12.x'
registry-url: 'https://registry.npmjs.org'
- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
publish-git:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '12.x'
registry-url: 'https://npm.pkg.github.com'
scope: '@contentstack'
- run: npm ci
- run: npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
13 changes: 13 additions & 0 deletions lib/contentstack.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ import httpClient from './core/contentstackHTTPClient.js'
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client({ headers: { 'headerkey': 'value'} })
*
* @prop {string=} params.authtoken - Optional Authtoken is a read-write token used to make authorized CMA requests, but it is a user-specific token.
* @example //Set the `authtoken`
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client({ authtoken: 'value' })
*
* @prop {string=} params.timeout - Optional authorization token is a read-write token used to make authorized CMA requests, but it is a user-specific token.
* @example //Set the `authorization`
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client({ authorization: 'Bearer <token_value>' })
*
* @prop {number=} params.timeout - Optional number of milliseconds before the request times out. Default is 30000ms
* @example //Set the `timeout` to 50000ms
* import * as contentstack from '@contentstack/management'
Expand Down Expand Up @@ -132,6 +142,9 @@ export function client (params = {}) {
if (params.authtoken) {
requiredHeaders.authtoken = params.authtoken
}
if (params.authorization) {
requiredHeaders.authorization = params.authorization
}
params = {
...defaultParameter,
...clonedeep(params)
Expand Down
43 changes: 42 additions & 1 deletion lib/stack/asset/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,52 @@ export function Asset (http, data = {}) {
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack().asset().query({ query: { filename: 'Asset Name' } }).find()
* 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
}

Expand Down
54 changes: 53 additions & 1 deletion lib/stack/contentType/entry/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,58 @@ export function Entry (http, data) {
throw error(err)
}
}

/**
* @description The Set Entry Workflow Stage request allows you to either set a particular workflow stage of an entry or update the workflow stage details of an entry.
* @memberof Entry
* @func setWorkflowStage
* @returns {Promise<Object>} Response Object.
* @param {Object} publishing_rule Details for the publish request
* @param {String} locale Enter the code of the locale that the entry belongs to.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* const workflow_stage = {
* "comment": "Workflow Comment",
* "due_date": "Thu Dec 01 2018",
* "notify": false,
* "uid": "workflow_stage_uid",
* "assigned_to": [{
* "uid": "user_uid",
* "name": "Username",
* "email": "user_email_id"
* }],
* "assigned_by_roles": [{
* "uid": "role_uid",
* "name": "Role name"
* }]
* }
* client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry('uid').publishRequest({ publishing_rule, locale: 'en-us'})
* .then((response) => console.log(response.notice));
*/
this.setWorkflowStage = async ({workflow_stage, locale}) => {
const publishDetails = {
workflow: { workflow_stage }
}
const headers = {}
if (this.stackHeaders) {
headers.headers = this.stackHeaders
}
headers.params = {
locale
}
try {
const response = await http.post(`${this.urlPath}/workflow`, publishDetails, headers)
if (response.data) {
return response.data
} else {
throw error(response)
}
} catch (err) {
throw error(err)
}
}
} else {
/**
* @description The Create an entry call creates a new entry for the selected content type.
Expand Down Expand Up @@ -239,7 +291,7 @@ export function Entry (http, data) {
* client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry()
* .import({
* entry: 'path/to/file.json',
* overright: true
* overwrite: true
* })
* .then((entry) => console.log(entry))
*
Expand Down
37 changes: 37 additions & 0 deletions lib/stack/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,43 @@ export function Stack (http, data) {
}
}

/**
* @description The Update User Role API Request updates the roles of an existing user account.
* This API Request will override the existing roles assigned to a user
* @memberof Stack
* @func updateUsersRoles
* @param {*} users object containing userId and array of roles to assign user.
* @returns {Object} Response Object.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
* const users = {
* user_uid: ['role_uid_1', 'role_uid_2' ]
* }
*
* client.stack({ api_key: 'api_key'}).updateUsersRoles(users)
* .then((response) => console.log(response.notice))
*
*/
this.updateUsersRoles = async (users) => {
try {
const response = await http.post(`${this.urlPath}/users/roles`,
{ users },
{
headers: {
...cloneDeep(this.stackHeaders)
}
})
if (response.data) {
return UserCollection(http, response.data.stack)
} else {
return error(response)
}
} catch (err) {
return error(err)
}
}

/**
* @description The Transfer stack ownership to other users call sends the specified user an email invitation for accepting the ownership of a particular stack.
* @memberof Stack
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@contentstack/management",
"version": "1.3.1",
"version": "1.4.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",
Expand Down
20 changes: 19 additions & 1 deletion test/api/asset-test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import path from 'path'
import { expect } from 'chai'
import { describe, it, setup } from 'mocha'
import { jsonReader } from '../utility/fileOperations/readwrite'
import { jsonReader, writeDownloadedFile } from '../utility/fileOperations/readwrite'
import { contentstackClient } from '../utility/ContentstackClient.js'

var client = {}
Expand All @@ -10,6 +10,7 @@ var stack = {}
var folderUID = ''
var assetUID = ''
var publishAssetUID = ''
var assetURL = ''
describe('Assets api Test', () => {
setup(() => {
const user = jsonReader('loggedinuser.json')
Expand All @@ -27,6 +28,7 @@ describe('Assets api Test', () => {
makeAsset().create(asset)
.then((asset) => {
assetUID = asset.uid
assetURL = asset.url
expect(asset.uid).to.be.not.equal(null)
expect(asset.url).to.be.not.equal(null)
expect(asset.filename).to.be.equal('customUpload.html')
Expand All @@ -38,6 +40,22 @@ describe('Assets api Test', () => {
.catch(done)
})

it('Download asset from URL.', done => {
makeAsset().download({ url: assetURL, responseType: 'stream' })
.then((response) => {
writeDownloadedFile(response, 'asset1')
done()
}).catch(done)
})
it('Download asset from fetch details ', done => {
makeAsset(assetUID).fetch()
.then((asset) => asset.download({ responseType: 'stream' }))
.then((response) => {
writeDownloadedFile(response, 'asset2')
done()
}).catch(done)
})

it('Create folder ', done => {
makeAsset().folder().create({ asset: { name: 'Sample Folder' } })
.then((asset) => {
Expand Down
24 changes: 23 additions & 1 deletion test/typescript/asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import path from "path";
var assetUID = ''
var folderUID = ''
var publishAssetUID = ''

var assetURL = ''
export function createAsset(stack: Stack) {
describe('Asset create', () => {
test('Asset Upload', done => {
Expand All @@ -17,6 +17,7 @@ export function createAsset(stack: Stack) {
stack.asset().create(asset)
.then((asset) => {
assetUID = asset.uid
assetURL = asset.url
expect(asset.uid).to.be.not.equal(null)
expect(asset.url).to.be.not.equal(null)
expect(asset.filename).to.be.equal('customUpload.html')
Expand Down Expand Up @@ -67,6 +68,27 @@ export function createAsset(stack: Stack) {
})
}

export function downloadAsset(stack: Stack) {
describe('Asset download', () => {
test('Download asset from url', done => {
stack.asset().download({url: assetURL, responseType: 'stream'})
.then((_) => {
done()
})
.catch(done)
})

test('Download asset from uid', done => {
stack.asset(assetUID).fetch()
.then((asset) => asset.download({responseType: 'stream'}))
.then((_) => {
done()
})
.catch(done)
})
})
}

export function replaceAsset(stack: Stack) {
describe('Asset replace', () => {
test('Replace Asset', done => {
Expand Down
3 changes: 2 additions & 1 deletion test/typescript/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as dotenv from 'dotenv'
import { shareStack, stacks, stackTest, unshareStack } from './stack';
import { contentType, createContentType, queryContentType } from './contentType';
import { createEntry, getEntries, importEntry, publishUnpublishEntry } from './entry';
import { createAsset, deleteAsset, getAssets, publishUnpublishAsset, queryOnAsset, replaceAsset } from './asset';
import { createAsset, deleteAsset, downloadAsset, getAssets, publishUnpublishAsset, queryOnAsset, replaceAsset } from './asset';
import { createGlobalField, globalField, queryGlobalField } from './globalField';
import { createBranch, deleteBranch, queryBranch } from './branch';
import { createBranchAlias, deleteBranchAlias, queryBranchAlias } from './branchAlias';
Expand Down Expand Up @@ -76,6 +76,7 @@ describe('Typescript API test', () => {
importEntry(stack)

createAsset(stack)
downloadAsset(stack)
replaceAsset(stack)
getAssets(stack)
publishUnpublishAsset(stack)
Expand Down
32 changes: 32 additions & 0 deletions test/unit/entry-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,38 @@ describe('Contentstack Entry test', () => {
.catch(done)
})

it('Entry set Workflow stage test', done => {
var mock = new MockAdapter(Axios);

mock.post('/content_types/content_type_uid/entries/UID/workflow').reply(200, {
...noticeMock
})

const workflow_stage = {
uid: 'uid',
comment: 'Please review this.',
due_date: 'Thu Dec 01 2018',
notify: true,
assigned_to: [{
uid: "user_uid",
name: "Username",
email: "user_email_id"
}],
assigned_by_roles: [{
uid: "role_uid",
name: "Role name"
}]
}

makeEntry({entry: { ...systemUidMock }})
.setWorkflowStage({workflow_stage, locale: 'en-us'})
.then((response) => {
expect(response.notice).to.be.equal(noticeMock.notice)
done()
})
.catch(done)
})

it('Entry publish request test', done => {
var mock = new MockAdapter(Axios)
mock.onPost('/content_types/content_type_uid/entries/UID/workflow').reply(200, {
Expand Down
Loading