Skip to content

DX | 01-04-2025 #306

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 37 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
38439b9
feat: added oauth support
aman19K Feb 27, 2025
13f2bef
fix: snyk issue
aman19K Feb 28, 2025
fb32783
Merge pull request #279 from contentstack/feat/DX-2206
aman19K Feb 28, 2025
aa892ba
feat: added getter & setter methods for access token, refresh
aman19K Mar 1, 2025
7efbab2
feat: retry the requests that were pending due to token expiration
aman19K Mar 7, 2025
5e1c49a
Merge pull request #285 from contentstack/feat/DX-1364
aman19K Mar 7, 2025
2736ef7
Merge branch 'development' into feat/oauth-support
aman19K Mar 10, 2025
682b5bd
feat: oauth unit test cases
aman19K Mar 11, 2025
fce8e8e
Merge pull request #296 from contentstack/staging
cs-raj Mar 12, 2025
1122a41
Merge branch 'development' into feat/oauth-support
aman19K Mar 13, 2025
2f411ae
fix: lint issues
aman19K Mar 13, 2025
a6b5510
Merge branch 'feat/oauth-support' into feat/DX-2264-oauth-test-cases
aman19K Mar 13, 2025
6fa265a
fix: oauth unit test cases linting issues
aman19K Mar 13, 2025
c141f42
fix: oauth unit test cases
aman19K Mar 17, 2025
48db1d3
refactor: update Slack message when tests are failed
harshithad0703 Mar 17, 2025
a86ec2d
fix:linting issue in test/unit/ContentstackHTTPClient-test.js
aman19K Mar 17, 2025
97876b4
feat: oauth integration test cases
aman19K Mar 17, 2025
b310d86
fix: refresh &updated token url
aman19K Mar 17, 2025
4744444
Merge pull request #297 from contentstack/feat/DX-2264-oauth-test-cases
aman19K Mar 17, 2025
e004efb
Fixed CLI error issue
sunil-lakshman Mar 18, 2025
eb1d48f
Fixed lint errors
sunil-lakshman Mar 18, 2025
9a8bdcf
Fixed linting errors
sunil-lakshman Mar 18, 2025
76c65a5
Added version and changelog file
sunil-lakshman Mar 19, 2025
2b1f913
Merge pull request #302 from contentstack/staging
reeshika-h Mar 20, 2025
c86e357
Merge branch 'development' into feat/oauth-support
aman19K Mar 20, 2025
4d67187
fix: update Slack channel for message notifications
harshithad0703 Mar 24, 2025
ee516f0
updated axios version & change log
aman19K Mar 26, 2025
41685f3
Merge branch 'development' into fix/dx-2317-slack-fail-msg
harshithad0703 Mar 26, 2025
96fc069
Buffer upload in assets (#303)
sunil-lakshman Mar 26, 2025
851c96d
update axios
harshithad0703 Mar 26, 2025
2264ba5
Merge pull request #298 from contentstack/fix/dx-2317-slack-fail-msg
harshithad0703 Mar 26, 2025
52b49fc
Merge branch 'development' into fix/1694-global-fields
sunil-lakshman Mar 26, 2025
2a877cd
Merge pull request #305 from contentstack/fix/global-fields
sunil-lakshman Mar 26, 2025
300b90f
Merge branch 'development' into feat/oauth-support
aman19K Mar 26, 2025
9b7be05
Merge pull request #304 from contentstack/feat/oauth-support
aman19K Mar 26, 2025
30703ce
Update CHANGELOG
harshithad0703 Mar 26, 2025
5e1785c
Merge pull request #307 from contentstack/fix/changelog
harshithad0703 Mar 26, 2025
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
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## [v1.20.0](https://github.com/contentstack/contentstack-management-javascript/tree/v1.20.0) (2025-04-01)
- Feature
- Added OAuth support
- Added the Unit Test cases and added sanity test case for OAuth
- Handle retry the requests that were pending due to token expiration
- Updated Axios Version
- Enhancement
- Added stack headers in global fields response
- Added buffer upload in assets

## [v1.19.5](https://github.com/contentstack/contentstack-management-javascript/tree/v1.19.5) (2025-03-17)
- Fix
- Added AuditLog in the stack class
Expand Down
35 changes: 34 additions & 1 deletion lib/contentstackClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Organization } from './organization/index'
import cloneDeep from 'lodash/cloneDeep'
import { User } from './user/index'
import error from './core/contentstackError'
import OAuthHandler from './core/oauthHandler'

export default function contentstackClient ({ http }) {
/**
Expand Down Expand Up @@ -172,12 +173,44 @@ export default function contentstackClient ({ http }) {
}, error)
}

/**
* @description The oauth call is used to sign in to your Contentstack account and obtain the accesstoken.
* @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
* @example
* import * as contentstack from '@contentstack/management'
* const client = contentstack.client()
*
* client.oauth({ appId: <appId>, clientId: <clientId>, redirectUri: <redirectUri>, clientSecret: <clientSecret>, responseType: <responseType>, scope: <scope> })
* .then(() => console.log('Logged in successfully'))
*
*/
function oauth (params = {}) {
http.defaults.versioningStrategy = 'path'
const appId = params.appId || '6400aa06db64de001a31c8a9'
const clientId = params.clientId || 'Ie0FEfTzlfAHL4xM'
const redirectUri = params.redirectUri || 'http://localhost:8184'
const responseType = params.responseType || 'code'
const scope = params.scope
const clientSecret = params.clientSecret
return new OAuthHandler(http, appId, clientId, redirectUri, clientSecret, responseType, scope)
}

return {
login: login,
logout: logout,
getUser: getUser,
stack: stack,
organization: organization,
axiosInstance: http
axiosInstance: http,
oauth
}
}
57 changes: 48 additions & 9 deletions lib/core/concurrency-queue.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Axios from 'axios'
import OAuthHandler from './oauthHandler'
const defaultConfig = {
maxRequests: 5,
retryLimit: 5,
Expand Down Expand Up @@ -75,17 +76,17 @@ export function ConcurrencyQueue ({ axios, config }) {
request.formdata = request.data
request.data = transformFormData(request)
}
request.retryCount = request.retryCount || 0
if (request.headers.authorization && request.headers.authorization !== undefined) {
if (this.config.authorization && this.config.authorization !== undefined) {
request.headers.authorization = this.config.authorization
request.authorization = this.config.authorization
if (axios?.oauth?.accessToken) {
const isTokenExpired = axios.oauth.tokenExpiryTime && Date.now() > axios.oauth.tokenExpiryTime
if (isTokenExpired) {
return refreshAccessToken().catch((error) => {
throw new Error('Failed to refresh access token: ' + error.message)
})
}
delete request.headers.authtoken
} else if (request.headers.authtoken && request.headers.authtoken !== undefined && this.config.authtoken && this.config.authtoken !== undefined) {
request.headers.authtoken = this.config.authtoken
request.authtoken = this.config.authtoken
}

request.retryCount = request?.retryCount || 0
setAuthorizationHeaders(request)
if (request.cancelToken === undefined) {
const source = Axios.CancelToken.source()
request.cancelToken = source.token
Expand All @@ -108,6 +109,44 @@ export function ConcurrencyQueue ({ axios, config }) {
})
}

const setAuthorizationHeaders = (request) => {
if (request.headers.authorization && request.headers.authorization !== undefined) {
if (this.config.authorization && this.config.authorization !== undefined) {
request.headers.authorization = this.config.authorization
request.authorization = this.config.authorization
}
delete request.headers.authtoken
} else if (request.headers.authtoken && request.headers.authtoken !== undefined && this.config.authtoken && this.config.authtoken !== undefined) {
request.headers.authtoken = this.config.authtoken
request.authtoken = this.config.authtoken
} else if (axios?.oauth?.accessToken) {
// If OAuth access token is available in axios instance
request.headers.authorization = `Bearer ${axios.oauth.accessToken}`
request.authorization = `Bearer ${axios.oauth.accessToken}`
delete request.headers.authtoken
}
}

// Refresh Access Token
const refreshAccessToken = async () => {
try {
// Try to refresh the token
await new OAuthHandler(axios).refreshAccessToken()
this.paused = false // Resume the request queue once the token is refreshed

// Retry the requests that were pending due to token expiration
this.running.forEach(({ request, resolve, reject }) => {
// Retry the request
axios(request).then(resolve).catch(reject)
})
this.running = [] // Clear the running queue after retrying requests
} catch (error) {
this.paused = false // stop queueing requests on failure
this.running.forEach(({ reject }) => reject(error)) // Reject all queued requests
this.running = [] // Clear the running queue
}
}

const delay = (time, isRefreshToken = false) => {
if (!this.paused) {
this.paused = true
Expand Down
22 changes: 22 additions & 0 deletions lib/core/contentstackHTTPClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,31 @@ 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?.startsWith('api')) {
uiHostName = uiHostName.replace('api', 'app')
}
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
baseURL,
uiBaseUrl,
developerHubBaseUrl,
...config,
paramsSerializer: function (params) {
var query = params.query
Expand Down
Loading
Loading