Skip to content
15 changes: 12 additions & 3 deletions lib/contentstack.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import httpClient from './core/contentstackHTTPClient.js'
* const client = contentstack.client()
*
* @param {object} params - Client initialization parameters
* @param {Object=} param.proxy -
* @param {Object=} params.proxy - Proxy configuration object for HTTP requests
* @param {string=} params.region - Region for API endpoint (NA, EU, AU, AZURE_NA, AZURE_EU, GCP_NA, GCP_EU)
* @param {string=} params.feature - Feature identifier for user agent
* @param {string=} params.refreshToken - Refresh token for OAuth authentication
* @prop {string=} params.endpoint - API endpoint that a service will talk to
* @example //Set the `endpoint` to 'https://api.contentstack.io:{port}/{version}'
* import * as contentstack from '@contentstack/management'
Expand All @@ -39,7 +42,7 @@ import httpClient from './core/contentstackHTTPClient.js'
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client({ authtoken: 'value' })
*
* @prop {string=} params.early_access - Optional early_access is a token used for early access of new features in CMA requests.
* @prop {Array<string>=} params.early_access - Optional array of early access tokens used for early access of new features in CMA requests.
* @example //Set the `early_access`
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client({ early_access: ['ea1', 'ea2'] })
Expand Down Expand Up @@ -158,7 +161,13 @@ import httpClient from './core/contentstackHTTPClient.js'
*
* @prop {string=} params.application - Application name and version e.g myApp/version
* @prop {string=} params.integration - Integration name and version e.g react/version
* @returns Contentstack.Client
* @prop {string=} params.region - API region. Valid values: 'na', 'eu', 'au', 'azure_na', 'azure_eu', 'gcp_na', 'gcp_eu' (default: 'na')
* @example //Set the `region` to 'eu'
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client({ region: 'eu' })
*
* @prop {string=} params.feature - Feature identifier for user agent header
* @returns {ContentstackClient} Instance of ContentstackClient
*/
export function client (params = {}) {
let defaultHostName = getRegionEndpoint('na')
Expand Down
33 changes: 18 additions & 15 deletions lib/contentstackClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export default function contentstackClient ({ http }) {
* @prop {string} parameters.password - password for user to login
* @prop {string} parameters.tfa_token - tfa token for user to login (2FA token)
* @prop {string} parameters.mfaSecret - TOTP secret key for generating 2FA token
* @returns {Promise}
* @param {Object=} params - Optional request parameters
* @returns {Promise<Object>} Promise for login response
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
Expand Down Expand Up @@ -59,7 +60,8 @@ export default function contentstackClient ({ http }) {
* The information returned includes details of the stacks owned by and shared with the specified user account.
* @memberof ContentstackClient
* @func getUser
* @returns {Promise}
* @param {Object=} params - Optional request parameters
* @returns {Promise<Object>} Promise for User instance
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
Expand All @@ -78,10 +80,11 @@ export default function contentstackClient ({ http }) {
* @description Get Stack instance. A stack is a space that stores the content of a project.
* @memberof ContentstackClient
* @func stack
* @param {String} api_key - Stack API Key
* @param {String} management_token - Management token for Stack.
* @param {String} branch_name - Branch name or alias to access specific branch. Default is master.
* @returns {Stack} Instance of Stack
* @param {Object=} params - Stack initialization parameters
* @prop {String} params.api_key - Stack API Key
* @prop {String} params.management_token - Management token for Stack.
* @prop {String} params.branch_uid - Branch UID or alias to access specific branch. Default is master.
* @returns {Stack} Instance of Stack.
*
* @example
* import * as contentstack from '@contentstack/management'
Expand Down Expand Up @@ -121,7 +124,7 @@ export default function contentstackClient ({ http }) {
* @description Organization is the top-level entity in the hierarchy of Contentstack, consisting of stacks and stack resources, and users.
* @memberof ContentstackClient
* @func organization
* @param {String} uid - Organization UID.
* @param {String=} uid - Organization UID. If not provided, returns organization instance for querying all organizations.
* @returns {Organization} Instance of Organization.
*
* @example
Expand Down Expand Up @@ -152,7 +155,7 @@ export default function contentstackClient ({ http }) {
* @memberof ContentstackClient
* @param {String} authtoken - Authtoken to logout from.
* @func logout
* @returns {Object} Response object.
* @returns {Promise<Object>} Promise for response object.
*
* @example
* import * as contentstack from '@contentstack/management'
Expand Down Expand Up @@ -195,13 +198,13 @@ export default function contentstackClient ({ http }) {
* @memberof ContentstackClient
* @func oauth
* @param {Object} parameters - oauth parameters
* @prop {string} parameters.appId - appId of the application
* @prop {string} parameters.clientId - clientId of the application
* @prop {string} parameters.clientId - clientId of the application
* @prop {string} parameters.responseType - responseType
* @prop {string} parameters.scope - scope
* @prop {string} parameters.clientSecret - clientSecret of the application
* @returns {OAuthHandler} Instance of OAuthHandler
* @prop {string=} parameters.appId - appId of the application (default: '6400aa06db64de001a31c8a9')
* @prop {string=} parameters.clientId - clientId of the application (default: 'Ie0FEfTzlfAHL4xM')
* @prop {string=} parameters.redirectUri - redirect URI for OAuth callback (default: 'http://localhost:8184')
* @prop {string=} parameters.responseType - responseType (default: 'code')
* @prop {string=} parameters.scope - scope
* @prop {string=} parameters.clientSecret - clientSecret of the application
* @returns {OAuthHandler} Instance of OAuthHandler.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
Expand Down
7 changes: 7 additions & 0 deletions lib/contentstackCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
* @namespace ContentstackCollection
*/
export default class ContentstackCollection {
/**
* Creates a ContentstackCollection instance.
* @param {Object} response - HTTP response object.
* @param {Object} http - HTTP client instance.
* @param {Object=} stackHeaders - Stack headers to include in data.
* @param {Function=} wrapperCollection - Collection wrapper function to transform items.
*/
constructor (response, http, stackHeaders = null, wrapperCollection) {
const data = response.data || {}
if (stackHeaders) {
Expand Down
25 changes: 25 additions & 0 deletions lib/core/concurrency-queue.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,31 @@ const defaultConfig = {
delayMs: null // Delay in milliseconds before making each request
}

/**
* Creates a concurrency queue manager for Axios requests with retry logic and rate limiting.
* @param {Object} options - Configuration options.
* @param {Object} options.axios - Axios instance to manage.
* @param {Object=} options.config - Queue configuration options.
* @param {number=} options.config.maxRequests - Maximum concurrent requests, defaults to 5.
* @param {number=} options.config.retryLimit - Maximum retry attempts for errors, defaults to 5.
* @param {number=} options.config.retryDelay - Delay between retries in milliseconds, defaults to 300.
* @param {boolean=} options.config.retryOnError - Enable retry on error, defaults to true.
* @param {boolean=} options.config.retryOnNetworkFailure - Enable retry on network failures, defaults to true.
* @param {boolean=} options.config.retryOnDnsFailure - Enable retry on DNS failures, defaults to true.
* @param {boolean=} options.config.retryOnSocketFailure - Enable retry on socket failures, defaults to true.
* @param {boolean=} options.config.retryOnHttpServerError - Enable retry on HTTP 5xx errors, defaults to true.
* @param {number=} options.config.maxNetworkRetries - Maximum network retry attempts, defaults to 3.
* @param {number=} options.config.networkRetryDelay - Base delay for network retries in milliseconds, defaults to 100.
* @param {string=} options.config.networkBackoffStrategy - Backoff strategy ('exponential' or 'fixed'), defaults to 'exponential'.
* @param {number=} options.config.delayMs - Delay before each request in milliseconds.
* @param {Function=} options.config.retryCondition - Custom function to determine if error can be retried.
* @param {Function=} options.config.logHandler - Log handler function.
* @param {Function=} options.config.refreshToken - Token refresh function.
* @param {string=} options.config.authtoken - Auth token.
* @param {string=} options.config.authorization - Authorization token.
* @returns {Object} ConcurrencyQueue instance with request/response interceptors attached to Axios.
* @throws {Error} If axios instance is not provided or configuration is invalid.
*/
export function ConcurrencyQueue ({ axios, config }) {
if (!axios) {
throw Error('Axios instance is not present')
Expand Down
11 changes: 10 additions & 1 deletion lib/core/contentstackError.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@

/**
* Formats and throws an error from an HTTP error response.
* @param {Object} errorResponse - Error response object from HTTP request.
* @param {Object} errorResponse.config - Request configuration object.
* @param {Object} errorResponse.response - HTTP response object.
* @param {number} errorResponse.response.status - HTTP status code.
* @param {string} errorResponse.response.statusText - HTTP status text.
* @param {Object} errorResponse.response.data - Response data containing error details.
* @throws {Error} Formatted error object with request and response details.
*/
export default function error (errorResponse) {
const config = errorResponse.config
const response = errorResponse.response
Expand Down
63 changes: 37 additions & 26 deletions lib/core/oauthHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import errorFormatter from './contentstackError'
/**
* @description OAuthHandler class to handle OAuth authorization and token management
* @class OAuthHandler
* @param {any} axiosInstance
* @param {any} appId
* @param {any} clientId
* @param {any} redirectUri
* @param {any} responseType='code'
* @param {any} clientSecret
* @param {any} scope=[]
* @returns {OAuthHandler} OAuthHandler instance
* @param {Object} axiosInstance - Axios HTTP client instance.
* @param {string=} appId - Application ID, defaults to '6400aa06db64de001a31c8a9'.
* @param {string=} clientId - Client ID, defaults to 'Ie0FEfTzlfAHL4xM'.
* @param {string=} redirectUri - Redirect URI for OAuth callback, defaults to 'http://localhost:8184'.
* @param {string=} clientSecret - Client secret. If provided, PKCE will be skipped.
* @param {string=} responseType - Response type, defaults to 'code'.
* @param {Array<string>=} scope - OAuth scope array, defaults to [].
* @returns {OAuthHandler} OAuthHandler instance.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand Down Expand Up @@ -80,7 +80,8 @@ export default class OAuthHandler {
* @description Authorize the user by redirecting to the OAuth provider's authorization page
* @memberof OAuthHandler
* @func authorize
* @returns {any} Authorization URL
* @async
* @returns {Promise<string>} Promise that resolves to authorization URL
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand Down Expand Up @@ -114,8 +115,9 @@ export default class OAuthHandler {
* @description Exchange the authorization code for an access token
* @memberof OAuthHandler
* @func exchangeCodeForToken
* @param {any} code - Authorization code received from the OAuth provider
* @returns {any} Token data
* @async
* @param {string} code - Authorization code received from the OAuth provider
* @returns {Promise<Object>} Promise that resolves to token data object
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand Down Expand Up @@ -155,9 +157,10 @@ export default class OAuthHandler {
* @description Refreshes the access token using the provided refresh token or the one stored in the axios instance.
* @memberof OAuthHandler
* @func refreshAccessToken
* @async
* @param {string|null} [providedRefreshToken=null] - The refresh token to use for refreshing the access token. If not provided, the stored refresh token will be used.
* @returns {Promise<Object>} - A promise that resolves to the response data containing the new access token, refresh token, and expiry time.
* @throws {Error} - Throws an error if no refresh token is available or if the token refresh request fails.
* @returns {Promise<Object>} A promise that resolves to the response data containing the new access token, refresh token, and expiry time.
* @throws {Error} Throws an error if no refresh token is available or if the token refresh request fails.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand Down Expand Up @@ -196,8 +199,9 @@ export default class OAuthHandler {
* @description Logs out the user by revoking the OAuth app authorization
* @memberof OAuthHandler
* @func logout
* @returns {Promise<string>} - A promise that resolves to a success message if the logout was successful.
* @throws {Error} - Throws an error if the logout request fails.
* @async
* @returns {Promise<string>} A promise that resolves to a success message if the logout was successful.
* @throws {Error} Throws an error if the logout request fails.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand All @@ -219,7 +223,7 @@ export default class OAuthHandler {
* @description Get the current access token
* @memberof OAuthHandler
* @func getAccessToken
* @returns {any}
* @returns {string|undefined} Current access token or undefined if not set.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand Down Expand Up @@ -294,7 +298,8 @@ export default class OAuthHandler {
* @description Set the access token in the axios instance
* @memberof OAuthHandler
* @func setAccessToken
* @param {*} token
* @param {string} token - Access token to set.
* @throws {Error} Throws an error if token is not provided.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand All @@ -312,7 +317,8 @@ export default class OAuthHandler {
* @description Set the refresh token in the axios instance
* @memberof OAuthHandler
* @func setRefreshToken
* @param {*} token
* @param {string} token - Refresh token to set.
* @throws {Error} Throws an error if token is not provided.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand All @@ -330,7 +336,8 @@ export default class OAuthHandler {
* @description Set the organization UID in the axios instance
* @memberof OAuthHandler
* @func setOrganizationUID
* @param {*} organizationUID
* @param {string} organizationUID - Organization UID to set.
* @throws {Error} Throws an error if organizationUID is not provided.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand All @@ -348,7 +355,8 @@ export default class OAuthHandler {
* @description Set the user UID in the axios instance
* @memberof OAuthHandler
* @func setUserUID
* @param {*} userUID
* @param {string} userUID - User UID to set.
* @throws {Error} Throws an error if userUID is not provided.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand All @@ -366,7 +374,8 @@ export default class OAuthHandler {
* @description Set the token expiry time in the axios instance
* @memberof OAuthHandler
* @func setTokenExpiryTime
* @param {*} expiryTime
* @param {number} expiryTime - Token expiry time (timestamp in milliseconds).
* @throws {Error} Throws an error if expiryTime is not provided.
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand All @@ -386,8 +395,8 @@ export default class OAuthHandler {
* @func handleRedirect
* @async
* @param {string} url - The URL to handle after the OAuth authorization
* @returns {Promise<void>} - A promise that resolves if the redirect URL is successfully handled
* @throws {Error} - Throws an error if the authorization code is not found in the redirect URL
* @returns {Promise<void>} A promise that resolves if the redirect URL is successfully handled
* @throws {Error} Throws an error if the authorization code is not found in the redirect URL
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client();
Expand All @@ -413,7 +422,8 @@ export default class OAuthHandler {
* @description Get the OAuth app authorization for the current user
* @memberof OAuthHandler
* @func getOauthAppAuthorization
* @returns {any}
* @async
* @returns {Promise<string>} Promise that resolves to authorization UID
*/
async getOauthAppAuthorization () {
const headers = {
Expand Down Expand Up @@ -448,8 +458,9 @@ export default class OAuthHandler {
* @description Revoke the OAuth app authorization for the current user
* @memberof OAuthHandler
* @func revokeOauthAppAuthorization
* @param {any} authorizationId
* @returns {any}
* @async
* @param {string} authorizationId - Authorization ID to revoke
* @returns {Promise<Object>} Promise that resolves to response data
*/
async revokeOauthAppAuthorization (authorizationId) {
if (authorizationId?.length > 1) {
Expand Down
Loading
Loading