Skip to content
Open
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
17 changes: 12 additions & 5 deletions .talismanrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
fileignoreconfig:
- filename: pnpm-lock.yaml
checksum: 0f2e17618b7c8286c5f76d4e25a98b830d3eb2d29acc6f8099f3501ff150d4f4
- filename: packages/contentstack-utilities/src/message-handler.ts
checksum: e7221e8413005b9efe3a230cd91aff130850976addc41c0acb10745a56ec3245
version: '1.0'

- filename: pnpm-lock.yaml
checksum: 0f2e17618b7c8286c5f76d4e25a98b830d3eb2d29acc6f8099f3501ff150d4f4
- filename: packages/contentstack-utilities/src/message-handler.ts
checksum: e7221e8413005b9efe3a230cd91aff130850976addc41c0acb10745a56ec3245
- filename: packages/contentstack-utilities/src/feature-status/build-auth-headers.ts
checksum: 9360dfbce41aa9c8a62889f4821c37fc222b04b8b1c552d1dfbcd8f2854d49e0
- filename: packages/contentstack/src/hooks/prerun/plan-guard.ts
checksum: 74eeb5c98e9ae48bf6f2918e75a7cfca23915396ffdd177b8716acba35c287da
- filename: packages/contentstack/README.md
checksum: c0f958f9650e7a26133758e4d0ceae34cdf736e7f54e1cf9114694e9c041f2a0
version: '1.0'
2 changes: 1 addition & 1 deletion packages/contentstack-auth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ $ npm install -g @contentstack/cli-auth
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-auth/2.0.0-beta.10 darwin-arm64 node-v22.13.1
@contentstack/cli-auth/2.0.0-beta.13 darwin-arm64 node-v24.18.0
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-command/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ abstract class ContentstackCommand extends Command {

get context() {
// @ts-ignore
return this.config.context || {};
return this.config.context || this.config.options?.context || {};
}

get email() {
Expand Down
32 changes: 16 additions & 16 deletions packages/contentstack-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ $ npm install -g @contentstack/cli-config
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-config/2.0.0-beta.7 darwin-arm64 node-v22.13.1
@contentstack/cli-config/2.0.0-beta.11 darwin-arm64 node-v24.18.0
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down Expand Up @@ -457,25 +457,25 @@ Set region for CLI
```
USAGE
$ csdx config:set:region [REGION] [--cda <value> --cma <value> --ui-host <value> -n <value>] [--developer-hub
<value>] [--personalize <value>] [--launch <value>] [--studio <value>] [--asset-management <value>]
<value>] [--personalize <value>] [--launch <value>] [--studio <value>] [--cs-assets <value>] [--auth-api <value>]

ARGUMENTS
[REGION] Name for the region

FLAGS
-n, --name=<value> Name for the region, if this flag is added then cda, cma and ui-host flags are
required
--asset-management=<value> Custom host to set for Asset Management API
--cda=<value> Custom host to set for content delivery API, if this flag is added then cma, ui-host
and name flags are required
--cma=<value> Custom host to set for content management API, , if this flag is added then cda,
ui-host and name flags are required
--developer-hub=<value> Custom host to set for Developer hub API
--launch=<value> Custom host to set for Launch API
--personalize=<value> Custom host to set for Personalize API
--studio=<value> Custom host to set for Studio API
--ui-host=<value> Custom UI host to set for CLI, if this flag is added then cda, cma and name flags are
required
-n, --name=<value> Name for the region, if this flag is added then cda, cma and ui-host flags are required
--auth-api=<value> Custom host to set for Auth API
--cda=<value> Custom host to set for content delivery API, if this flag is added then cma, ui-host and
name flags are required
--cma=<value> Custom host to set for content management API, , if this flag is added then cda, ui-host
and name flags are required
--cs-assets=<value> Custom host to set for Contentstack Assets API
--developer-hub=<value> Custom host to set for Developer hub API
--launch=<value> Custom host to set for Launch API
--personalize=<value> Custom host to set for Personalize API
--studio=<value> Custom host to set for Studio API
--ui-host=<value> Custom UI host to set for CLI, if this flag is added then cda, cma and name flags are
required

DESCRIPTION
Set region for CLI
Expand Down Expand Up @@ -507,7 +507,7 @@ EXAMPLES

$ csdx config:set:region --cma <custom_cma_host_url> --cda <custom_cda_host_url> --ui-host <custom_ui_host_url> --name "India" --studio <custom_studio_url>

$ csdx config:set:region --cma <custom_cma_host_url> --cda <custom_cda_host_url> --ui-host <custom_ui_host_url> --name "India" --asset-management <asset_management_url>
$ csdx config:set:region --cma <custom_cma_host_url> --cda <custom_cda_host_url> --ui-host <custom_ui_host_url> --name "India" --cs-assets <cs_assets_url>

$ csdx config:set:region --cda <custom_cda_host_url> --cma <custom_cma_host_url> --ui-host <custom_ui_host_url> --name "India" --developer-hub <custom_developer_hub_url> --launch <custom_launch_url> --personalize <custom_personalize_url> --studio <custom_studio_url>
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ export default class RegionSetCommand extends BaseCommand<typeof RegionSetComman
'cs-assets': _flags.string({
description: 'Custom host to set for Contentstack Assets API',
}),
'auth-api': _flags.string({
description: 'Custom host to set for Auth API',
}),
};
static examples = [
'$ csdx config:set:region',
Expand Down Expand Up @@ -83,6 +86,7 @@ export default class RegionSetCommand extends BaseCommand<typeof RegionSetComman
let launchHubUrl = regionSetFlags['launch'];
let composableStudioUrl = regionSetFlags['studio'];
let csAssetsUrl = regionSetFlags['cs-assets'];
let authUrl = regionSetFlags['auth-api'];
let selectedRegion = args.region;
if (!(cda && cma && uiHost && name) && !selectedRegion) {
selectedRegion = await interactive.askRegions();
Expand Down Expand Up @@ -116,6 +120,9 @@ export default class RegionSetCommand extends BaseCommand<typeof RegionSetComman
if (!csAssetsUrl) {
csAssetsUrl = this.transformUrl(cma, 'am-api');
}
if (!authUrl) {
authUrl = this.transformUrl(cma, 'auth-api');
}
let customRegion: Region = {
cda,
cma,
Expand All @@ -126,6 +133,7 @@ export default class RegionSetCommand extends BaseCommand<typeof RegionSetComman
launchHubUrl,
composableStudioUrl,
csAssetsUrl,
authUrl,
};
customRegion = regionHandler.setCustomRegion(customRegion);
await authHandler.setConfigData('logout'); //Todo: Handle this logout flow well through logout command call
Expand All @@ -138,6 +146,7 @@ export default class RegionSetCommand extends BaseCommand<typeof RegionSetComman
cliux.success(`Launch URL: ${customRegion.launchHubUrl}`);
cliux.success(`Studio URL: ${customRegion.composableStudioUrl}`);
cliux.success(`Contentstack Assets URL: ${customRegion.csAssetsUrl}`);
cliux.success(`Auth API URL: ${customRegion.authUrl}`);
} catch (error) {
handleAndLogError(error, { ...this.contextDetails, module: 'config-set-region' });
}
Expand Down
1 change: 1 addition & 0 deletions packages/contentstack-config/src/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface Region {
launchHubUrl: string;
composableStudioUrl: string;
csAssetsUrl?: string;
authUrl?: string;
}

export interface Limit {
Expand Down
2 changes: 2 additions & 0 deletions packages/contentstack-config/src/utils/region-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function getRegionObject(regionKey: string): Region {
personalizeUrl: endpoints.personalizeManagement,
composableStudioUrl: endpoints.composableStudio,
csAssetsUrl: endpoints.assetManagement,
authUrl: endpoints.auth,
};
} catch {
return null;
Expand Down Expand Up @@ -157,6 +158,7 @@ class UserConfig {
launchHubUrl: regionObject['launchHubUrl'],
composableStudioUrl: regionObject['composableStudioUrl'],
csAssetsUrl: regionObject['csAssetsUrl'],
authUrl: regionObject['authUrl'],
};

return sanitizedRegion;
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-utilities/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@contentstack/cli-utilities",
"version": "2.0.0-beta.9",
"version": "2.0.0-beta.10",
"description": "Utilities for contentstack projects",
"main": "lib/index.js",
"types": "lib/index.d.ts",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import configHandler from '../config-handler';

export interface AuthHeaders {
[key: string]: string;
}

export function buildAuthHeaders(ctx?: {
managementToken?: string;
apiKey?: string;
authToken?: string;
orgUid?: string;
}): AuthHeaders {
// 1. Management token takes priority (no 'Bearer' prefix — API contract)
if (ctx?.managementToken && ctx?.apiKey) {
return {
Authorization: ctx.managementToken,
api_key: ctx.apiKey,
};
}

// 2. OAuth
const oauthToken = configHandler.get('oauthAccessToken') as string | undefined;
if (oauthToken) {
return { Authorization: `Bearer ${oauthToken}` };
}

// 3. Authtoken + organization_uid
const authtoken = ctx?.authToken ?? (configHandler.get('authtoken') as string | undefined);
const orgUid = ctx?.orgUid ?? (configHandler.get('oauthOrgUid') as string | undefined);
if (authtoken && orgUid) {
return { authtoken, organization_uid: orgUid };
}

// 4. Authtoken + api_key
if (authtoken && ctx?.apiKey) {
return { authtoken, api_key: ctx.apiKey };
}

throw new Error(
'PLAN_CHECK: Cannot build auth headers — no valid credentials available. ' +
'Please log in or provide a management token alias.',
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { HttpClient } from '../http-client';
import { resolveAuthHost } from './resolve-auth-host';
import { buildAuthHeaders } from './build-auth-headers';
import { FeatureStatus, FeatureCtx } from './types';

export async function isFeatureEnabled(featureUid: string, ctx?: FeatureCtx): Promise<FeatureStatus> {
const host = resolveAuthHost(ctx);
const headers = buildAuthHeaders(ctx);

const client = new HttpClient();
client.baseUrl(host).headers(headers);

const res = await client.get<FeatureStatus>(
`/v1/feature-status?feature_uid=${encodeURIComponent(featureUid)}`,
);

if (res.status < 200 || res.status >= 300) {
throw new Error(`PLAN_CHECK: feature-status API returned ${res.status} for "${featureUid}".`);
}

return res.data as FeatureStatus;
}

export async function assertFeatureEnabled(featureUid: string, ctx?: FeatureCtx): Promise<FeatureStatus> {
let status: FeatureStatus;
try {
status = await isFeatureEnabled(featureUid, ctx);
} catch (e) {
throw new Error(
`Could not verify your plan for "${featureUid}". ` +
`This command requires a confirmed plan status to run. ` +
`Please retry; if the problem persists contact support. (${(e as Error).message})`,
);
}

if (!status.is_part_of_plan) {
throw new Error(
`"${featureUid}" is not part of your current plan. Please upgrade your plan to use this feature.`,
);
}

if (status.status !== 'enabled') {
throw new Error(
`"${featureUid}" is not enabled for your plan (status: ${status.status}).`,
);
}

return status;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const FEATURE = {
ASSET_MANAGEMENT: 'amAssets',
ASSET_SCANNING: 'assetsScan',
} as const;

export type FeatureUid = (typeof FEATURE)[keyof typeof FEATURE];
5 changes: 5 additions & 0 deletions packages/contentstack-utilities/src/feature-status/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './types';
export * from './feature-uids';
export { resolveAuthHost } from './resolve-auth-host';
export { buildAuthHeaders } from './build-auth-headers';
export { isFeatureEnabled, assertFeatureEnabled } from './feature-status-handler';
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import configHandler from '../config-handler';

export function resolveAuthHost(ctx?: { region?: { authUrl?: string } }): string {
const region = (ctx?.region ?? configHandler.get('region')) as { authUrl?: string } | undefined;
const authUrl = region?.authUrl;
if (!authUrl) {
throw new Error(
'PLAN_CHECK: Auth host is not configured for the current region. ' +
"Re-run `csdx config:set:region` to refresh region endpoints.",
);
}
return String(authUrl).replace(/\/$/, '');
}
16 changes: 16 additions & 0 deletions packages/contentstack-utilities/src/feature-status/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export interface FeatureStatus {
org_uid: string;
feature_key: string;
status: 'enabled' | 'disabled' | string;
limit: number;
max_limit: number;
is_part_of_plan: boolean;
}

export interface FeatureCtx {
apiKey?: string;
orgUid?: string;
managementToken?: string;
authToken?: string;
region?: { authUrl?: string; name?: string; cma?: string };
}
4 changes: 3 additions & 1 deletion packages/contentstack-utilities/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,6 @@ export {
ProgressStrategyRegistry,
CustomProgressStrategy,
DefaultProgressStrategy
} from './progress-summary';
} from './progress-summary';

export * from './feature-status';
Loading