Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,6 @@ tsconfig.json

# next.js build output
.next
.dccache
dist
jsdocs
14 changes: 1 addition & 13 deletions .talismanrc
Original file line number Diff line number Diff line change
@@ -1,13 +1 @@
fileignoreconfig:
- filename: jsdocs/stack_environment_index.js.html
checksum: 506ccc2492c3ce3218582ba049ee4713b33eb20764227a91f16a10f76ff0a8e7
- filename: dist/react-native/contentstack-management.js
checksum: 279b809bc382f5bc1898525d49d8e49ee3ed82ce8e4728416fef22a8fa0fab81
- filename: dist/web/contentstack-management.js
checksum: 62b3396f8d0e8981f299815d3cef4f77f389097e2600e6cf04b6dbc24d4822c7
- filename: dist/nativescript/contentstack-management.js
checksum: 52e66c545bb73f49d75863242e128dc08e3672a5d0291d5e14a360581ad2e71c
- filename: dist/node/contentstack-management.js
checksum: 62d9cc89bdf76f1ef8ccb676e896247bdf689f58716bbceadc174d8ef6fce621
- filename: package-lock.json
checksum: 05fa93e24eaaa69794388ce1d818e3518373919d0d8243f9f921d10086dafbb1
threshold: medium
27 changes: 27 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## Security

Contentstack takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations.

If you believe you have found a security vulnerability in any Contentstack-owned repository, please report it to us as described below.

## Reporting Security Issues

**Please do not report security vulnerabilities through public GitHub issues.**

Send email to [[email protected]](mailto:[email protected]).

You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message.

Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:

* Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
* Full paths of source file(s) related to the manifestation of the issue
* The location of the affected source code (tag/branch/commit or direct URL)
* Any special configuration required to reproduce the issue
* Step-by-step instructions to reproduce the issue
* Proof-of-concept or exploit code (if possible)
* Impact of the issue, including how an attacker might exploit the issue

This information will help us triage your report more quickly.

[https://www.contentstack.com/trust/](https://www.contentstack.com/trust/)
11 changes: 11 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
roots: ['<rootDir>'],
transform: {
'^.+\\.ts?$': 'ts-jest'
},
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.ts?$',
moduleFileExtensions: ['ts', 'js', 'json', 'node'],
collectCoverage: true,
clearMocks: true,
coverageDirectory: 'coverage'
}
286 changes: 286 additions & 0 deletions lib/stack/contentType/entry/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
import cloneDeep from 'lodash/cloneDeep'
import { create,
update,
deleteEntity,
fetch,
query,
upload,
parseData,
publish,
unpublish }
from '../../../entity'
import FormData from 'form-data'
import { createReadStream } from 'fs'
import error from '../../../core/contentstackError'

/**
* An entry is the actual piece of content created using one of the defined content types. Read more about <a href='https://www.contentstack.com/docs/guide/content-management'>Entries</a>.
* @namespace Entry
*/

export function Entry (http, data) {
this.stackHeaders = data.stackHeaders
this.content_type_uid = data.content_type_uid
this.urlPath = `/content_types/${this.content_type_uid}/entries`

if (data && data.entry) {
Object.assign(this, cloneDeep(data.entry))
this.urlPath = `/content_types/${this.content_type_uid}/entries/${this.uid}`

/**
* @description The Create an entry call creates a new entry for the selected content type.
* @memberof Entry
* @func update
* @param locale - Locale code to localized entry
* @returns {Promise<Entry.Entry>} Promise for Entry instance
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry('uid').fetch()
* .then((entry) => {
* entry.title = 'My New Entry'
* entry.description = 'Entry description'
* return entry.update()
* })
* .then((entry) => console.log(entry))
*
* @example
* // To Localize Entry pass locale in parameter
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry('uid').fetch()
* .then((entry) => {
* entry.title = 'My New Entry'
* entry.description = 'Entry description'
* return entry.update({ locale: 'en-at' })
* })
* .then((entry) => console.log(entry))
*
*/
this.update = update(http, 'entry')

/**
* @description The Delete an entry call is used to delete a specific entry from a content type.
* @memberof Entry
* @func delete
* @returns {Object} Response Object.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry('uid').delete()
* .then((response) => console.log(response.notice))
*/
this.delete = deleteEntity(http)

/**
* @description The fetch Entry call fetches Entry details.
* @memberof Entry
* @func fetch
* @param {Int} version Enter the version number of the entry that you want to retrieve. However, to retrieve a specific version of an entry, you need to keep the environment parameter blank.
* @param {Int} locale Enter the code of the language of which the entries need to be included. Only the entries published in this locale will be displayed.
* @param {Int} include_workflow Enter 'true' to include the workflow details of the entry.
* @param {Int} include_publish_details Enter 'true' to include the publish details of the entry.
* @returns {Promise<Entry.Entry>} Promise for Entry instance
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry('uid').fetch()
* .then((entry) => console.log(entry))
*
*/
this.fetch = fetch(http, 'entry')

/**
* @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 Entry
* @func publish
* @returns {Promise<Object>} Response Object.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* const entry = {
* "locales": [
* "en-us"
* ],
* "environments": [
* "development"
* ]
* }
*
* client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry('uid').publish({ publishDetails: entry, locale: "en-us", version: 1, scheduledAt: "2019-02-08T18:30:00.000Z"})
* .then((response) => console.log(response.notice))
*
*/
this.publish = publish(http, 'entry')

/**
* @description The Replace asset call will replace an existing asset with another file on the stack.
* @memberof Entry
* @func unpublish
* @returns {Promise<Object>} Response Object.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* const entry = {
* "locales": [
* "en-us"
* ],
* "environments": [
* "development"
* ]
* }
*
* client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry('uid').unpublish({ publishDetails: entry, locale: "en-us", version: 1, scheduledAt: "2019-02-08T18:30:00.000Z"})
* .then((response) => console.log(response.notice))
*
*/
this.unpublish = unpublish(http, 'entry')

/**
* @description This multipurpose request allows you to either send a publish request or accept/reject a received publish request.
* @memberof Entry
* @func publishRequest
* @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 publishing_rule = {
* "uid": "uid",
* "action": "publish" //(‘publish’, ‘unpublish’, or ’both’)
* "status": 1, //(this could be ‘0’ for Approval Requested, ‘1’ for ‘Approval Accepted’, and ‘-1’ for ‘Approval Rejected’),
* "notify": false,
* comment": "Please review this."
* }
* 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.publishRequest = async ({publishing_rule, locale}) => {
const publishDetails = {
workflow: { publishing_rule }
}
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.
* @memberof Entry
* @func create
* @returns {Promise<Entry.Entry>} Promise for Entry instance
*
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
* const entry = {
* title: 'Sample Entry',
* url: '/sampleEntry'
* }
* client.stack().contentType('content_type_uid').entry().create({ entry })
* .then((entry) => console.log(entry))
*/
this.create = create({ http: http })

/**
* @description The Query on Entry will allow to fetch details of all or specific Entry
* @memberof Entry
* @func query
* @param {Int} locale Enter the code of the language of which the entries need to be included. Only the entries published in this locale will be displayed.
* @param {Int} include_workflow Enter 'true' to include the workflow details of the entry.
* @param {Int} include_publish_details Enter 'true' to include the publish details of the entry.
* @param {Object} query Queries that you can use to fetch filtered results.
* @returns {Array<Entry>} Array of Entry.
*
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack().contentType('content_type_uid').entry().query({ query: { title: 'Entry title' } }).find()
* .then((entries) => console.log(entries))
*/
this.query = query({ http: http, wrapperCollection: EntryCollection })
}

/**
* @description The Import Entry calls given below help you to import entries by uploading JSON files.
* @memberof Entry
* @func import
* @param {String} entry Select the JSON file of the entry that you wish to import.
* @param {String} locale Enter the code of the language to import the entry of that particular language.
* @param {Boolean} overwrite Select 'true' to replace an existing entry with the imported entry file.
*
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.stack({ api_key: 'api_key'}).contentType('content_type_uid').entry()
* .import({
* entry: 'path/to/file.json',
* overright: true
* })
* .then((entry) => console.log(entry))
*
*/
this.import = async ({ entry, locale = null, overwrite = false }) => {
var importUrl = `${this.urlPath}/import?overwrite=${overwrite}`
if (locale) {
importUrl = `${importUrl}&locale=${locale}`
}
try {
const response = await upload({
http: http,
urlPath: importUrl,
stackHeaders: this.stackHeaders,
formData: createFormData(entry)
})
if (response.data) {
return new this.constructor(http, parseData(response, this.stackHeaders))
} else {
throw error(response)
}
} catch (err) {
throw error(err)
}
}
return this
}

export function EntryCollection (http, data) {
const obj = cloneDeep(data.entries) || []
const entryCollection = obj.map((entry) => {
return new Entry(http, { entry: entry, content_type_uid: data.content_type_uid, stackHeaders: data.stackHeaders })
})
return entryCollection
}

export function createFormData (entry) {
return () => {
const formData = new FormData()
const uploadStream = createReadStream(entry)
formData.append('entry', uploadStream)
return formData
}
}
Loading