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
9 changes: 8 additions & 1 deletion .talismanrc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ fileignoreconfig:
ignore_detectors:
- filecontent
- filename: package-lock.json
checksum: bab53d56ce2609e960fdbbd1e87cc89915820e6761016ddd74ee57f931f4223d
checksum: 1475ee2c6a615f4e6f8393f4a209398aa6b827e7d036302c6fc065d5914e8292
- filename: .husky/pre-commit
checksum: 52a664f536cf5d1be0bea19cb6031ca6e8107b45b6314fe7d47b7fad7d800632
- filename: test/sanity-check/api/user-test.js
Expand All @@ -30,4 +30,11 @@ fileignoreconfig:
checksum: b76ca091caa3a1b2658cd422a2d8ef3ac9996aea0aff3f982d56bb309a3d9fde
- filename: test/unit/ContentstackClient-test.js
checksum: 974a4f335aef025b657d139bb290233a69bed1976b947c3c674e97baffe4ce2f
- filename: test/unit/ContentstackHTTPClient-test.js
checksum: 4043efd843e24da9afd0272c55ef4b0432e3374b2ca12b913f1a6654df3f62be
- filename: test/unit/contentstack-test.js
checksum: 2597efae3c1ab8cc173d5bf205f1c76932211f8e0eb2a16444e055d83481976c
version: "1.0"



10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## [v1.25.2](https://github.com/contentstack/contentstack-management-javascript/tree/v1.25.2) (2025-10-28)
- Fix
- Fixed HTTP client region endpoint initialization to default to 'na' region when region parameter is not provided
- Test
- Added comprehensive test coverage for region endpoint functionality
- Added 48 test cases for getRegionEndpoint function covering all supported regions, aliases, and service endpoints
- Added 14 test cases for region configuration in client initialization
- Added 13 test cases for HTTP client region integration
- All 626 tests passing with no regressions

## [v1.25.1](https://github.com/contentstack/contentstack-management-javascript/tree/v1.25.1) (2025-10-06)
- Fix
- Updated delay handling to use centralized external configuration in SDK interceptor
Expand Down
211 changes: 211 additions & 0 deletions lib/assets/regions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
{
"regions": [
{
"id": "na",
"name": "AWS North America",
"cloudProvider": "AWS",
"location": "North America",
"alias": [
"na",
"us",
"aws-na",
"aws_na"
],
"isDefault": true,
"endpoints": {
"application": "https://app.contentstack.com",
"contentDelivery": "https://cdn.contentstack.io",
"contentManagement": "https://api.contentstack.io",
"auth": "https://auth-api.contentstack.com",
"graphqlDelivery": "https://graphql.contentstack.com",
"preview": "https://rest-preview.contentstack.com",
"graphqlPreview": "https://graphql-preview.contentstack.com",
"images": "https://images.contentstack.io",
"assets": "https://assets.contentstack.io",
"automate": "https://automations-api.contentstack.com",
"launch": "https://launch-api.contentstack.com",
"developerHub": "https://developerhub-api.contentstack.com",
"brandKit": "https://brand-kits-api.contentstack.com",
"genAI": "https://ai.contentstack.com",
"personalize": "https://personalize-api.contentstack.com",
"personalizeEdge": "https://personalize-edge.contentstack.com"
}
},
{
"id": "eu",
"name": "AWS Europe",
"cloudProvider": "AWS",
"location": "Europe",
"alias": [
"eu",
"aws-eu",
"aws_eu"
],
"isDefault": false,
"endpoints": {
"application": "https://eu-app.contentstack.com",
"contentDelivery": "https://eu-cdn.contentstack.com",
"contentManagement": "https://eu-api.contentstack.com",
"auth": "https://eu-auth-api.contentstack.com",
"graphqlDelivery": "https://eu-graphql.contentstack.com",
"preview": "https://eu-rest-preview.contentstack.com",
"graphqlPreview": "https://eu-graphql-preview.contentstack.com",
"images": "https://eu-images.contentstack.com",
"assets": "https://eu-assets.contentstack.com",
"automate": "https://eu-prod-automations-api.contentstack.com",
"launch": "https://eu-launch-api.contentstack.com",
"developerHub": "https://eu-developerhub-api.contentstack.com",
"brandKit": "https://eu-brand-kits-api.contentstack.com",
"genAI": "https://eu-ai.contentstack.com",
"personalize": "https://eu-personalize-api.contentstack.com",
"personalizeEdge": "https://eu-personalize-edge.contentstack.com"
}
},
{
"id": "au",
"name": "AWS Australia",
"cloudProvider": "AWS",
"location": "Australia",
"alias": [
"au",
"aws-au",
"aws_au"
],
"isDefault": false,
"endpoints": {
"application": "https://au-app.contentstack.com",
"contentDelivery": "https://au-cdn.contentstack.com",
"contentManagement": "https://au-api.contentstack.com",
"auth": "https://au-auth-api.contentstack.com",
"graphqlDelivery": "https://au-graphql.contentstack.com",
"preview": "https://au-rest-preview.contentstack.com",
"graphqlPreview": "https://au-graphql-preview.contentstack.com",
"images": "https://au-images.contentstack.com",
"assets": "https://au-assets.contentstack.com",
"automate": "https://au-prod-automations-api.contentstack.com",
"launch": "https://au-launch-api.contentstack.com",
"developerHub": "https://au-developerhub-api.contentstack.com",
"brandKit": "https://au-brand-kits-api.contentstack.com",
"genAI": "https://au-ai.contentstack.com",
"personalize": "https://au-personalize-api.contentstack.com",
"personalizeEdge": "https://au-personalize-edge.contentstack.com"
}
},
{
"id": "azure-na",
"name": "Azure North America",
"cloudProvider": "Azure",
"location": "North America",
"alias": [
"azure-na",
"azure_na"
],
"isDefault": false,
"endpoints": {
"application": "https://azure-na-app.contentstack.com",
"contentDelivery": "https://azure-na-cdn.contentstack.com",
"contentManagement": "https://azure-na-api.contentstack.com",
"auth": "https://azure-na-auth-api.contentstack.com",
"graphqlDelivery": "https://azure-na-graphql.contentstack.com",
"preview": "https://azure-na-rest-preview.contentstack.com",
"graphqlPreview": "https://azure-na-graphql-preview.contentstack.com",
"images": "https://azure-na-images.contentstack.com",
"assets": "https://azure-na-assets.contentstack.com",
"automate": "https://azure-na-automations-api.contentstack.com",
"launch": "https://azure-na-launch-api.contentstack.com",
"developerHub": "https://azure-na-developerhub-api.contentstack.com",
"brandKit": "https://azure-na-brand-kits-api.contentstack.com",
"genAI": "https://azure-na-ai.contentstack.com",
"personalize": "https://azure-na-personalize-api.contentstack.com",
"personalizeEdge": "https://azure-na-personalize-edge.contentstack.com"
}
},
{
"id": "azure-eu",
"name": "Azure Europe",
"cloudProvider": "Azure",
"location": "Europe",
"alias": [
"azure-eu",
"azure_eu"
],
"isDefault": false,
"endpoints": {
"application": "https://azure-eu-app.contentstack.com",
"contentDelivery": "https://azure-eu-cdn.contentstack.com",
"contentManagement": "https://azure-eu-api.contentstack.com",
"auth": "https://azure-eu-auth-api.contentstack.com",
"graphqlDelivery": "https://azure-eu-graphql.contentstack.com",
"preview": "https://azure-eu-rest-preview.contentstack.com",
"graphqlPreview": "https://azure-eu-graphql-preview.contentstack.com",
"images": "https://azure-eu-images.contentstack.com",
"assets": "https://azure-eu-assets.contentstack.com",
"automate": "https://azure-eu-automations-api.contentstack.com",
"launch": "https://azure-eu-launch-api.contentstack.com",
"developerHub": "https://azure-eu-developerhub-api.contentstack.com",
"brandKit": "https://azure-eu-brand-kits-api.contentstack.com",
"genAI": "https://azure-eu-ai.contentstack.com",
"personalize": "https://azure-eu-personalize-api.contentstack.com",
"personalizeEdge": "https://azure-eu-personalize-edge.contentstack.com"
}
},
{
"id": "gcp-na",
"name": "GCP North America",
"cloudProvider": "GCP",
"location": "North America",
"alias": [
"gcp-na",
"gcp_na"
],
"isDefault": false,
"endpoints": {
"application": "https://gcp-na-app.contentstack.com",
"contentDelivery": "https://gcp-na-cdn.contentstack.com",
"contentManagement": "https://gcp-na-api.contentstack.com",
"auth": "https://gcp-na-auth-api.contentstack.com",
"graphqlDelivery": "https://gcp-na-graphql.contentstack.com",
"preview": "https://gcp-na-rest-preview.contentstack.com",
"graphqlPreview": "https://gcp-na-graphql-preview.contentstack.com",
"images": "https://gcp-na-images.contentstack.com",
"assets": "https://gcp-na-assets.contentstack.com",
"automate": "https://gcp-na-automations-api.contentstack.com",
"launch": "https://gcp-na-launch-api.contentstack.com",
"developerHub": "https://gcp-na-developerhub-api.contentstack.com",
"brandKit": "https://gcp-na-brand-kits-api.contentstack.com",
"genAI": "https://gcp-na-brand-kits-api.contentstack.com",
"personalize": "https://gcp-na-personalize-api.contentstack.com",
"personalizeEdge": "https://gcp-na-personalize-edge.contentstack.com"
}
},
{
"id": "gcp-eu",
"name": "GCP Europe",
"cloudProvider": "GCP",
"location": "Europe",
"alias": [
"gcp-eu",
"gcp_eu"
],
"isDefault": false,
"endpoints": {
"application": "https://gcp-eu-app.contentstack.com",
"contentDelivery": "https://gcp-eu-cdn.contentstack.com",
"contentManagement": "https://gcp-eu-api.contentstack.com",
"auth": "https://gcp-eu-auth-api.contentstack.com",
"graphqlDelivery": "https://gcp-eu-graphql.contentstack.com",
"preview": "https://gcp-eu-rest-preview.contentstack.com",
"graphqlPreview": "https://gcp-eu-graphql-preview.contentstack.com",
"images": "https://gcp-eu-images.contentstack.com",
"assets": "https://gcp-eu-assets.contentstack.com",
"automate": "https://gcp-eu-automations-api.contentstack.com",
"launch": "https://gcp-eu-launch-api.contentstack.com",
"developerHub": "https://gcp-eu-developerhub-api.contentstack.com",
"brandKit": "https://gcp-eu-brand-kits-api.contentstack.com",
"genAI": "https://gcp-eu-brand-kits-api.contentstack.com",
"personalize": "https://gcp-eu-personalize-api.contentstack.com",
"personalizeEdge": "https://gcp-eu-personalize-edge.contentstack.com"
}
}
]
}
23 changes: 3 additions & 20 deletions lib/contentstack.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,9 @@
*/
import packages from '../package.json'
import clonedeep from 'lodash/cloneDeep'
import getUserAgent from './core/Util.js'
import getUserAgent, { getRegionEndpoint } from './core/Util.js'
import contentstackClient from './contentstackClient.js'
import httpClient from './core/contentstackHTTPClient.js'
const regionHostMap = {
NA: 'api.contentstack.io',
EU: 'eu-api.contentstack.com',
AU: 'au-api.contentstack.com',
AZURE_NA: 'azure-na-api.contentstack.com',
AZURE_EU: 'azure-eu-api.contentstack.com',
GCP_NA: 'gcp-na-api.contentstack.com',
GCP_EU: 'gcp-eu-api.contentstack.com'
}

/**
* Create client instance
Expand Down Expand Up @@ -170,18 +161,10 @@ const regionHostMap = {
* @returns Contentstack.Client
*/
export function client (params = {}) {
let defaultHostName
let defaultHostName = getRegionEndpoint('na')

if (params.region) {
const region = params.region.toUpperCase()
if (!regionHostMap[region]) {
throw new Error(`Invalid region '${params.region}' provided. Allowed regions are: ${Object.keys(regionHostMap).join(', ')}`)
}
defaultHostName = regionHostMap[region]
} else if (params.host) {
defaultHostName = params.host
} else {
defaultHostName = regionHostMap['NA']
defaultHostName = getRegionEndpoint(params.region.toLowerCase())
}

const defaultParameter = {
Expand Down
13 changes: 13 additions & 0 deletions lib/core/Util.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { platform, release } from 'os'
import regionHostMap from '../assets/regions.json'

const HOST_REGEX = /^(?!(?:(?:https?|ftp):\/\/|internal|localhost|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)))(?:[\w-]+\.contentstack\.(?:io|com)(?::[^\/\s:]+)?|[\w-]+(?:\.[\w-]+)*(?::[^\/\s:]+)?)(?![\/?#])$/ // eslint-disable-line

export function isHost (host) {
Expand Down Expand Up @@ -235,3 +237,14 @@ export const validateAndSanitizeConfig = (config) => {
url: config.url.trim() // Sanitize URL by removing whitespace
}
}

export const getRegionEndpoint = (region, service = 'contentManagement') => {
const regionData = regionHostMap.regions.find(r =>
r.id === region ||
r.alias.some(alias => alias === region)
)
if (!regionData) {
throw new Error(`Invalid region '${region}' provided. Allowed regions are: ${regionHostMap.regions.map(r => r.id).join(', ')}`)
}
return regionData.endpoints[service]?.replace(/^https?:\/\//, '')
}
22 changes: 4 additions & 18 deletions lib/core/contentstackHTTPClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import axios from 'axios'
import clonedeep from 'lodash/cloneDeep'
import Qs from 'qs'
import { ConcurrencyQueue } from './concurrency-queue'
import { isHost } from './Util'
import { getRegionEndpoint, isHost } from './Util'

export default function contentstackHttpClient (options) {
const defaultConfig = {
Expand Down Expand Up @@ -68,25 +68,11 @@ export default function contentstackHttpClient (options) {
config.basePath = `/${config.basePath.split('/').filter(Boolean).join('/')}`
}
const baseURL = config.endpoint || `${protocol}://${hostname}:${port}${config.basePath}/{api-version}`
let uiHostName = hostname
let developerHubBaseUrl = hostname

if (uiHostName?.endsWith('io')) {
uiHostName = uiHostName.replace('io', 'com')
}

if (uiHostName) {
uiHostName = uiHostName.replace('api', 'app')
}
const region = config.region || 'na'
const uiHostName = getRegionEndpoint(region, 'application')
const developerHubBaseUrl = getRegionEndpoint(region, 'developerHub').replace(/^/, 'https://')
const uiBaseUrl = config.endpoint || `${protocol}://${uiHostName}`

developerHubBaseUrl = developerHubBaseUrl
?.replace('api', 'developerhub-api')
.replace(/^dev\d+/, 'dev') // Replaces any 'dev1', 'dev2', etc. with 'dev'
.replace('io', 'com')
.replace(/^http/, '') // Removing `http` if already present
.replace(/^/, 'https://') // Adds 'https://' at the start if not already there

// set ui host name
const axiosOptions = {
// Axios
Expand Down
Loading
Loading