Skip to content

Commit 3ff93e9

Browse files
Merge pull request #2509 from contentstack/main
back merge
2 parents 75413ba + 24e4651 commit 3ff93e9

File tree

8 files changed

+281
-270
lines changed

8 files changed

+281
-270
lines changed

.github/workflows/release-production-platform-plugins.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,6 @@ jobs:
3737
filename: .github/config/release.json
3838
prefix: release
3939

40-
# Dev Dependencies
41-
- name: Publishing dev dependencies (Production)
42-
uses: JS-DevTools/npm-publish@v3
43-
with:
44-
token: ${{ secrets.NPM_TOKEN }}
45-
package: ./packages/contentstack-dev-dependencies/package.json
46-
tag: latest
47-
4840
# Utilities
4941
- name: Publishing utilities (Production)
5042
uses: JS-DevTools/npm-publish@v3

.talismanrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ fileignoreconfig:
22
- filename: .github/workflows/release-production-pipeline.yml
33
checksum: 48264fdeb61cbbed348c7271aae5e155651f490aca063dbb1d54f2c15a154090
44
- filename: pnpm-lock.yaml
5-
checksum: 86aa5ecf1bce4a09ae5ee3027c28664b749bd95eaabffc51449ab4bfd99bfe69
5+
checksum: c64bb59690952523cb0c314de42499c168d3e08b1810e4583a546c5773bd89fc
66
version: '1.0'

packages/contentstack-utilities/src/contentstack-management-sdk.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import { client, ContentstackClient, ContentstackConfig } from '@contentstack/ma
22
import authHandler from './auth-handler';
33
import { Agent } from 'node:https';
44
import configHandler, { default as configStore } from './config-handler';
5-
import { getProxyConfigForHost, resolveRequestHost, clearProxyEnv } from './proxy-helper';
5+
import {
6+
getProxyConfigForHost,
7+
resolveRequestHost,
8+
clearProxyEnv,
9+
shouldBypassProxy,
10+
} from './proxy-helper';
611
import dotenv from 'dotenv';
712

813
dotenv.config();
@@ -22,13 +27,13 @@ class ManagementSDKInitiator {
2227
// NO_PROXY has priority over HTTP_PROXY/HTTPS_PROXY and config-set proxy
2328
const proxyConfig = getProxyConfigForHost(host);
2429

25-
// When bypassing, clear proxy env immediately so SDK never see it (they may read at init or first request).
26-
if (!proxyConfig) {
30+
// When NO_PROXY matches, strip proxy env so SDK/axios cannot pick up HTTP_PROXY for this process.
31+
if (host && shouldBypassProxy(host)) {
2732
clearProxyEnv();
2833
}
2934

3035
const option: ContentstackConfig = {
31-
host: config.host,
36+
host: config.host || host || undefined,
3237
maxContentLength: config.maxContentLength || 100000000,
3338
maxBodyLength: config.maxBodyLength || 1000000000,
3439
maxRequests: 10,
@@ -118,7 +123,10 @@ class ManagementSDKInitiator {
118123

119124
if (proxyConfig) {
120125
option.proxy = proxyConfig;
126+
} else if (host && shouldBypassProxy(host)) {
127+
option.proxy = false;
121128
}
129+
// When host is in NO_PROXY, do not add proxy to option at all
122130
if (config.endpoint) {
123131
option.endpoint = config.endpoint;
124132
}

packages/contentstack-utilities/src/http-client/client.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,25 @@ import { IHttpClient } from './client-interface';
33
import { HttpResponse } from './http-response';
44
import configStore from '../config-handler';
55
import authHandler from '../auth-handler';
6-
import { hasProxy, getProxyUrl, getProxyConfig, getProxyConfigForHost } from '../proxy-helper';
6+
import {
7+
hasProxy,
8+
getProxyUrl,
9+
getProxyConfigForHost,
10+
resolveRequestHost,
11+
shouldBypassProxy,
12+
} from '../proxy-helper';
713

814
/**
915
* Derive request host from baseURL or url for NO_PROXY checks.
1016
*/
1117
function getRequestHost(baseURL?: string, url?: string): string | undefined {
1218
const toTry = [baseURL, url].filter(Boolean) as string[];
13-
for (const candidateUrl of toTry) {
19+
for (const u of toTry) {
1420
try {
15-
const parsed = new URL(candidateUrl.startsWith('http') ? candidateUrl : `https://${candidateUrl}`);
21+
const parsed = new URL(u.startsWith('http') ? u : `https://${u}`);
1622
return parsed.hostname || undefined;
1723
} catch {
18-
// Invalid URL; try next candidate (baseURL or url)
24+
// ignore
1925
}
2026
}
2127
return undefined;
@@ -427,12 +433,14 @@ export class HttpClient implements IHttpClient {
427433
}
428434
}
429435

430-
// Configure proxy if available. NO_PROXY has priority: hosts in NO_PROXY never use proxy.
436+
// Configure proxy if available. NO_PROXY has priority; fall back to region CMA for host resolution.
431437
if (!this.request.proxy) {
432-
const host = getRequestHost(this.request.baseURL, url);
433-
const proxyConfig = host ? getProxyConfigForHost(host) : getProxyConfig();
438+
const host = getRequestHost(this.request.baseURL, url) || resolveRequestHost({});
439+
const proxyConfig = getProxyConfigForHost(host);
434440
if (proxyConfig) {
435441
this.request.proxy = proxyConfig;
442+
} else if (host && shouldBypassProxy(host)) {
443+
this.request.proxy = false;
436444
}
437445
}
438446

packages/contentstack-utilities/src/proxy-helper.ts

Lines changed: 64 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -82,44 +82,14 @@ export function shouldBypassProxy(host: string): boolean {
8282
}
8383

8484
/**
85-
* Get proxy configuration. Sources (in order): env (HTTP_PROXY/HTTPS_PROXY), then global config
86-
* from `csdx config:set:proxy --host <host> --port <port> --protocol <protocol>`.
85+
* Get proxy configuration. Priority order (per spec):
86+
* 1. Global CLI config from `csdx config:set:proxy --host <host> --port <port> --protocol <protocol>`
87+
* 2. Environment variables (HTTPS_PROXY or HTTP_PROXY)
8788
* For per-request use, prefer getProxyConfigForHost(host) so NO_PROXY overrides both sources.
8889
* @returns ProxyConfig object or undefined if no proxy is configured
8990
*/
9091
export function getProxyConfig(): ProxyConfig | undefined {
91-
// Priority 1: Environment variables (HTTPS_PROXY or HTTP_PROXY)
92-
const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
93-
94-
if (proxyUrl) {
95-
try {
96-
const url = new URL(proxyUrl);
97-
const defaultPort = url.protocol === 'https:' ? 443 : 80;
98-
const port = url.port ? Number.parseInt(url.port, 10) : defaultPort;
99-
100-
if (!Number.isNaN(port) && port >= 1 && port <= 65535) {
101-
const protocol = url.protocol.replace(':', '') as 'http' | 'https';
102-
const proxyConfig: ProxyConfig = {
103-
protocol: protocol,
104-
host: url.hostname,
105-
port: port,
106-
};
107-
108-
if (url.username || url.password) {
109-
proxyConfig.auth = {
110-
username: url.username,
111-
password: url.password,
112-
};
113-
}
114-
115-
return proxyConfig;
116-
}
117-
} catch {
118-
// Invalid URL, continue to check global config
119-
}
120-
}
121-
122-
// Priority 2: Global config (csdx config:set:proxy)
92+
// Priority 1: Global config (csdx config:set:proxy)
12393
const globalProxyConfig = configStore.get('proxy');
12494
if (globalProxyConfig) {
12595
if (typeof globalProxyConfig === 'object') {
@@ -151,11 +121,42 @@ export function getProxyConfig(): ProxyConfig | undefined {
151121
return proxyConfig;
152122
}
153123
} catch {
154-
// Invalid URL, return undefined
124+
// Invalid URL, continue to check environment
155125
}
156126
}
157127
}
158128

129+
// Priority 2: Environment variables (HTTPS_PROXY or HTTP_PROXY)
130+
const proxyUrl = process.env.HTTPS_PROXY || process.env.HTTP_PROXY;
131+
132+
if (proxyUrl) {
133+
try {
134+
const url = new URL(proxyUrl);
135+
const defaultPort = url.protocol === 'https:' ? 443 : 80;
136+
const port = url.port ? Number.parseInt(url.port, 10) : defaultPort;
137+
138+
if (!Number.isNaN(port) && port >= 1 && port <= 65535) {
139+
const protocol = url.protocol.replace(':', '') as 'http' | 'https';
140+
const proxyConfig: ProxyConfig = {
141+
protocol: protocol,
142+
host: url.hostname,
143+
port: port,
144+
};
145+
146+
if (url.username || url.password) {
147+
proxyConfig.auth = {
148+
username: url.username,
149+
password: url.password,
150+
};
151+
}
152+
153+
return proxyConfig;
154+
}
155+
} catch {
156+
// Invalid URL, return undefined
157+
}
158+
}
159+
159160
return undefined;
160161
}
161162

@@ -172,27 +173,38 @@ export function getProxyConfigForHost(host: string): ProxyConfig | undefined {
172173
return getProxyConfig();
173174
}
174175

176+
function regionCmaHostname(): string {
177+
const cma = configStore.get('region')?.cma;
178+
if (!cma || typeof cma !== 'string') {
179+
return '';
180+
}
181+
if (cma.startsWith('http')) {
182+
try {
183+
const u = new URL(cma);
184+
return u.hostname || cma;
185+
} catch {
186+
return cma;
187+
}
188+
}
189+
return cma;
190+
}
191+
175192
/**
176-
* Resolve request host for proxy/NO_PROXY checks: config.host or default CMA from region.
177-
* Use when the caller may omit host so NO_PROXY still applies (e.g. from region.cma).
178-
* @param config - Object with optional host (e.g. API client config)
179-
* @returns Host string (hostname or empty)
193+
* Hostname for NO_PROXY / proxy. Prefer `region.cma` when set so callers that pass a
194+
* default SDK host (e.g. bulk-entries -> api.contentstack.io) still match rules like
195+
* `.csnonprod.com` against the real API host (e.g. dev11-api.csnonprod.com).
180196
*/
181197
export function resolveRequestHost(config: { host?: string }): string {
182-
if (config.host) return config.host;
183-
const cma = configStore.get('region')?.cma;
184-
if (cma && typeof cma === 'string') {
185-
if (cma.startsWith('http')) {
186-
try {
187-
const u = new URL(cma);
188-
return u.hostname || cma;
189-
} catch {
190-
return cma;
191-
}
192-
}
193-
return cma;
198+
const fromRegion = regionCmaHostname();
199+
if (fromRegion) {
200+
return normalizeHost(fromRegion) || fromRegion;
201+
}
202+
203+
const raw = config.host?.trim() || '';
204+
if (!raw) {
205+
return '';
194206
}
195-
return '';
207+
return normalizeHost(raw) || raw;
196208
}
197209

198210
/**

packages/contentstack/package.json

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@contentstack/cli",
33
"description": "Command-line tool (CLI) to interact with Contentstack",
4-
"version": "1.59.0",
4+
"version": "1.60.0",
55
"author": "Contentstack",
66
"bin": {
77
"csdx": "./bin/run.js"
@@ -19,24 +19,24 @@
1919
"prepack": "pnpm compile && oclif manifest && oclif readme"
2020
},
2121
"dependencies": {
22-
"@contentstack/cli-audit": "~1.18.0",
23-
"@contentstack/cli-cm-export": "~1.23.2",
24-
"@contentstack/cli-cm-import": "~1.31.3",
25-
"@contentstack/cli-auth": "~1.7.3",
26-
"@contentstack/cli-cm-bootstrap": "~1.18.4",
27-
"@contentstack/cli-cm-branches": "~1.6.3",
28-
"@contentstack/cli-cm-bulk-publish": "~1.10.7",
29-
"@contentstack/cli-cm-clone": "~1.20.1",
30-
"@contentstack/cli-cm-export-to-csv": "~1.11.0",
31-
"@contentstack/cli-cm-import-setup": "~1.7.3",
22+
"@contentstack/cli-audit": "~1.19.0",
23+
"@contentstack/cli-cm-export": "~1.24.0",
24+
"@contentstack/cli-cm-import": "~1.32.0",
25+
"@contentstack/cli-auth": "~1.8.0",
26+
"@contentstack/cli-cm-bootstrap": "~1.19.0",
27+
"@contentstack/cli-cm-branches": "~1.7.0",
28+
"@contentstack/cli-cm-bulk-publish": "~1.11.0",
29+
"@contentstack/cli-cm-clone": "~1.21.0",
30+
"@contentstack/cli-cm-export-to-csv": "~1.12.0",
31+
"@contentstack/cli-cm-import-setup": "~1.8.0",
3232
"@contentstack/cli-cm-migrate-rte": "~1.6.4",
33-
"@contentstack/cli-cm-seed": "~1.14.3",
34-
"@contentstack/cli-command": "~1.7.2",
35-
"@contentstack/cli-config": "~1.19.0",
33+
"@contentstack/cli-cm-seed": "~1.15.0",
34+
"@contentstack/cli-command": "~1.8.0",
35+
"@contentstack/cli-config": "~1.20.0",
3636
"@contentstack/cli-launch": "^1.9.6",
37-
"@contentstack/cli-migration": "~1.11.0",
38-
"@contentstack/cli-utilities": "~1.17.4",
39-
"@contentstack/cli-variants": "~1.3.8",
37+
"@contentstack/cli-migration": "~1.12.0",
38+
"@contentstack/cli-utilities": "~1.18.0",
39+
"@contentstack/cli-variants": "~1.4.0",
4040
"@contentstack/management": "~1.27.5",
4141
"@oclif/core": "^4.8.3",
4242
"@oclif/plugin-help": "^6.2.28",

0 commit comments

Comments
 (0)