Skip to content

Feat/query support #2001

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 10 commits into from
Jul 21, 2025
Merged
Show file tree
Hide file tree
Changes from 3 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
4 changes: 3 additions & 1 deletion .talismanrc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
fileignoreconfig:
- filename: pnpm-lock.yaml
checksum: 612695c9e9d0a57c0996600c22ed44dc7929e926a619d30e753ab06310b22548
checksum: 0dcf1cfbae272f5c6143d09759f18316ba89c0aaaccdfe2aed0bd91f33d9e1c5
- filename: package-lock.json
checksum: b9f52a74faf44c3d112219ab78e72d41b0dc686a37a4aa1aaccbe8a7596c0683
- filename: packages/contentstack-import/test/integration/auth-token-modules/environments.test.js
checksum: bc6f06b75d082aaf99e2f2f4b932b143765e2f14086967fb8973fe1b2ca6c03e
- filename: packages/contentstack-import/test/integration/environments.test.js
Expand Down
7,441 changes: 3,628 additions & 3,813 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/contentstack-audit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ $ npm install -g @contentstack/cli-audit
$ csdx COMMAND
running command...
$ csdx (--version|-v)
@contentstack/cli-audit/1.13.0 darwin-x64 node-v22.17.0
@contentstack/cli-audit/1.13.0 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
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/1.4.1 darwin-x64 node-v22.17.0
@contentstack/cli-auth/1.4.1 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-bootstrap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ $ npm install -g @contentstack/cli-cm-bootstrap
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-cm-bootstrap/1.14.1 darwin-x64 node-v22.17.0
@contentstack/cli-cm-bootstrap/1.14.1 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-branches/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ $ npm install -g @contentstack/cli-cm-branches
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-cm-branches/1.4.3 darwin-x64 node-v22.17.0
@contentstack/cli-cm-branches/1.4.3 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-bulk-publish/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ $ npm install -g @contentstack/cli-cm-bulk-publish
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-cm-bulk-publish/1.8.2 darwin-x64 node-v22.17.0
@contentstack/cli-cm-bulk-publish/1.8.2 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-clone/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ $ npm install -g @contentstack/cli-cm-clone
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-cm-clone/1.14.2 darwin-x64 node-v22.17.0
@contentstack/cli-cm-clone/1.14.3 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion 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/1.13.0 darwin-x64 node-v22.17.0
@contentstack/cli-config/1.13.0 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-export/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ $ npm install -g @contentstack/cli-cm-export
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-cm-export/1.17.0 darwin-x64 node-v22.17.0
@contentstack/cli-cm-export/1.18.0 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-export/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@contentstack/cli-cm-export",
"description": "Contentstack CLI plugin to export content from stack",
"version": "1.17.0",
"version": "1.18.0",
"author": "Contentstack",
"bugs": "https://github.com/contentstack/cli/issues",
"dependencies": {
Expand Down
15 changes: 11 additions & 4 deletions packages/contentstack-export/src/commands/cm/stacks/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,19 +72,22 @@ export default class ExportCommand extends Command {
}),
module: flags.string({
char: 'm',
description: '[optional] Specific module name. If not specified, the export command will export all the modules to the stack. The available modules are assets, content-types, entries, environments, extensions, marketplace-apps, global-fields, labels, locales, webhooks, workflows, custom-roles, and taxonomies.',
description:
'[optional] Specific module name. If not specified, the export command will export all the modules to the stack. The available modules are assets, content-types, entries, environments, extensions, marketplace-apps, global-fields, labels, locales, webhooks, workflows, custom-roles, and taxonomies.',
parse: printFlagDeprecation(['-m'], ['--module']),
}),
'content-types': flags.string({
char: 't',
description: '[optional] The UID of the content type(s) whose content you want to export. In case of multiple content types, specify the IDs separated by spaces.',
description:
'[optional] The UID of the content type(s) whose content you want to export. In case of multiple content types, specify the IDs separated by spaces.',
multiple: true,
parse: printFlagDeprecation(['-t'], ['--content-types']),
}),
branch: flags.string({
char: 'B',
// default: 'main',
description: '[optional] The name of the branch where you want to export your content. If you don\'t mention the branch name, then by default the content will be exported from all the branches of your stack.',
description:
"[optional] The name of the branch where you want to export your content. If you don't mention the branch name, then by default the content will be exported from all the branches of your stack.",
parse: printFlagDeprecation(['-B'], ['--branch']),
}),
'secured-assets': flags.boolean({
Expand All @@ -95,6 +98,10 @@ export default class ExportCommand extends Command {
required: false,
description: '[optional] Force override all Marketplace prompts.',
}),
query: flags.string({
description: '[optional] Query object (inline JSON or file path) to filter module exports.',
hidden: true,
}),
};

static aliases: string[] = ['cm:export'];
Expand All @@ -107,7 +114,7 @@ export default class ExportCommand extends Command {
// Note setting host to create cma client
exportConfig.host = this.cmaHost;
exportConfig.region = this.region;
if(this.developerHubUrl) exportConfig.developerHubBaseUrl = this.developerHubUrl;
if (this.developerHubUrl) exportConfig.developerHubBaseUrl = this.developerHubUrl;
if (this.personalizeUrl) exportConfig.modules.personalize.baseURL[exportConfig.region.name] = this.personalizeUrl;
exportDir = sanitizePath(exportConfig.cliLogsPath || exportConfig.data || exportConfig.exportDir);
const managementAPIClient: ContentstackClient = await managementSDKClient(exportConfig);
Expand Down
21 changes: 14 additions & 7 deletions packages/contentstack-export/src/export/module-exporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,23 @@ class ModuleExporter {

async exportSingleModule(moduleName: Modules): Promise<void> {
// Note stack is always exported
let exportModules: Modules[] = ['stack'];
const {
modules: { [moduleName]: { dependencies = [] } = {} },
} = this.exportConfig;

if (dependencies.length > 0) {
exportModules = exportModules.concat(dependencies);
let exportModules: Modules[] = [];
if (!this.exportConfig.skipStackSettings) {
exportModules.push('stack');
}

exportModules.push(moduleName);

if (!this.exportConfig.skipDependencies) {
const {
modules: { [moduleName]: { dependencies = [] } = {} },
} = this.exportConfig;

if (dependencies.length > 0) {
exportModules = exportModules.concat(dependencies);
}
}

for (const moduleName of exportModules) {
await this.exportByModuleByName(moduleName);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ export default class ExportAssets extends BaseClass {
include_publish_details: true,
except: { BASE: this.assetConfig.invalidKeys },
};
this.applyQueryFilters(queryParam, 'assets');

if (this.assetConfig.includeVersionedAssets) {
const customHandler = (array: Array<any>) => {
Expand Down
14 changes: 14 additions & 0 deletions packages/contentstack-export/src/export/modules/base-class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,4 +187,18 @@ export default abstract class BaseClass {
return Promise.resolve();
}
}

protected applyQueryFilters(requestObject: any, moduleName: string): any {
if (this.exportConfig.query?.modules?.[moduleName]) {
const moduleQuery = this.exportConfig.query.modules[moduleName];
// Merge the query parameters with existing requestObject
if (moduleQuery) {
if (!requestObject.query) {
requestObject.query = moduleQuery;
}
Object.assign(requestObject.query, moduleQuery);
}
}
return requestObject;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default class ContentTypesExport extends BaseClass {
skip?: number;
limit?: number;
include_global_field_schema: boolean;
uid?: Record<string, string[]>
uid?: Record<string, string[]>;
};
private contentTypesConfig: {
dirName?: string;
Expand All @@ -38,11 +38,14 @@ export default class ContentTypesExport extends BaseClass {
include_global_field_schema: true,
};

// If content type id is provided then use it as part of query
if (Array.isArray(this.exportConfig.contentTypes) && this.exportConfig.contentTypes.length > 0) {
// If content type id is provided then use it as part of query
if (Array.isArray(this.exportConfig.contentTypes) && this.exportConfig.contentTypes.length > 0) {
this.qs.uid = { $in: this.exportConfig.contentTypes };
}

}

// Add after existing qs setup and before contentTypesDirPath
this.applyQueryFilters(this.qs, 'content-types');

this.contentTypesDirPath = path.resolve(
sanitizePath(exportConfig.data),
sanitizePath(exportConfig.branchName || ''),
Expand Down Expand Up @@ -99,7 +102,10 @@ export default class ContentTypesExport extends BaseClass {
async writeContentTypes(contentTypes: Record<string, unknown>[]) {
function write(contentType: Record<string, unknown>) {
return fsUtil.writeFile(
path.join(sanitizePath(this.contentTypesDirPath), sanitizePath(`${contentType.uid === 'schema' ? 'schema|1' : contentType.uid}.json`)),
path.join(
sanitizePath(this.contentTypesDirPath),
sanitizePath(`${contentType.uid === 'schema' ? 'schema|1' : contentType.uid}.json`),
),
contentType,
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export default class ExportExtensions extends BaseClass {
this.extensions = {};
this.extensionConfig = exportConfig.modules.extensions;
this.qs = { include_count: true };
this.applyQueryFilters(this.qs, 'extensions');
}

async start(): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ export default class GlobalFieldsExport extends BaseClass {
asc: 'updated_at',
include_count: true,
limit: this.globalFieldsConfig.limit,
include_global_field_schema: true
include_global_field_schema: true,
};
this.globalFieldsDirPath = path.resolve(
sanitizePath(exportConfig.data),
sanitizePath(exportConfig.branchName || ''),
sanitizePath(this.globalFieldsConfig.dirName),
);
this.globalFields = [];
this.applyQueryFilters(this.qs, 'global-fields');
}

async start() {
Expand All @@ -62,7 +63,7 @@ export default class GlobalFieldsExport extends BaseClass {
if (skip) {
this.qs.skip = skip;
}
let globalFieldsFetchResponse = await this.stackAPIClient.globalField({api_version: '3.2'}).query(this.qs).find();
let globalFieldsFetchResponse = await this.stackAPIClient.globalField({ api_version: '3.2' }).query(this.qs).find();
if (Array.isArray(globalFieldsFetchResponse.items) && globalFieldsFetchResponse.items.length > 0) {
this.sanitizeAttribs(globalFieldsFetchResponse.items);
skip += this.globalFieldsConfig.limit || 100;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export default class ExportTaxonomies extends BaseClass {
this.taxonomies = {};
this.taxonomiesConfig = exportConfig.modules.taxonomies;
this.qs = { include_count: true, limit: this.taxonomiesConfig.limit || 100, skip: 0 };
this.applyQueryFilters(this.qs, 'taxonomies');
}

async start(): Promise<void> {
Expand Down
3 changes: 3 additions & 0 deletions packages/contentstack-export/src/types/export-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default interface ExportConfig extends DefaultConfig {
singleModuleExport?: boolean;
moduleName?: Modules;
master_locale: masterLocale;
query?: any; // Added query field
headers?: {
api_key: string;
access_token?: string;
Expand All @@ -30,6 +31,8 @@ export default interface ExportConfig extends DefaultConfig {
source_stack?: string;
sourceStackName?: string;
region: Region;
skipStackSettings?: boolean;
skipDependencies?: boolean;
}

type branch = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ const setupConfig = async (exportCmdFlags: any): Promise<ExportConfig> => {
const externalConfig = await readFile(exportCmdFlags['config']);
config = merge.recursive(config, externalConfig);
}
config.exportDir = sanitizePath(exportCmdFlags['data'] || exportCmdFlags['data-dir'] || config.data || (await askExportDir()));
config.exportDir = sanitizePath(
exportCmdFlags['data'] || exportCmdFlags['data-dir'] || config.data || (await askExportDir()),
);

const pattern = /[*$%#<>{}!&?]/g;
if (pattern.test(config.exportDir)) {
Expand Down Expand Up @@ -81,6 +83,30 @@ const setupConfig = async (exportCmdFlags: any): Promise<ExportConfig> => {
if (Array.isArray(config.filteredModules) && config.filteredModules.length > 0) {
config.modules.types = filter(defaultConfig.modules.types, (module) => includes(config.filteredModules, module));
}

// Handle query flag - can be inline JSON or file path
if (exportCmdFlags['query']) {
try {
const queryInput = exportCmdFlags['query'];

// Check if it's a file path (contains .json extension or path separators)
if (queryInput.includes('.json') || queryInput.includes('/') || queryInput.includes('\\')) {
// Try to read as file path
try {
config.query = await readFile(queryInput);
} catch (fileError) {
// If file read fails, treat as inline JSON
config.query = JSON.parse(queryInput);
}
} else {
// Parse as inline JSON
config.query = JSON.parse(queryInput);
}
} catch (error) {
throw new Error(`Invalid query format: ${error.message}`);
}
}

return config;
};

Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-import-setup/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ $ npm install -g @contentstack/cli-cm-import-setup
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-cm-import-setup/1.3.0 darwin-x64 node-v22.17.0
@contentstack/cli-cm-import-setup/1.3.0 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-import/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ $ npm install -g @contentstack/cli-cm-import
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-cm-import/1.24.0 darwin-x64 node-v22.17.0
@contentstack/cli-cm-import/1.25.0 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-migrate-rte/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ $ npm install -g @contentstack/cli-cm-migrate-rte
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-cm-migrate-rte/1.5.2 darwin-x64 node-v22.17.0
@contentstack/cli-cm-migrate-rte/1.5.2 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
2 changes: 1 addition & 1 deletion packages/contentstack-migration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ $ npm install -g @contentstack/cli-migration
$ csdx COMMAND
running command...
$ csdx (--version)
@contentstack/cli-migration/1.7.3 darwin-x64 node-v22.17.0
@contentstack/cli-migration/1.7.3 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down
6 changes: 3 additions & 3 deletions packages/contentstack/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ $ npm install -g @contentstack/cli
$ csdx COMMAND
running command...
$ csdx (--version|-v)
@contentstack/cli/1.42.0 darwin-x64 node-v22.17.0
@contentstack/cli/1.43.0 darwin-arm64 node-v22.13.1
$ csdx --help [COMMAND]
USAGE
$ csdx COMMAND
Expand Down Expand Up @@ -3774,8 +3774,8 @@ USAGE
$ csdx launch:functions [-p <value>] [-d <value>]

FLAGS
-d, --data-dir=<value> [default: /Users/netraj.patel/netraj/projects/contentstack/cli/cli/packages/contentstack]
Current working directory
-d, --data-dir=<value> [default: /Users/shafeeq.pp/WORKSPACE/CLI/cli-org/cli-10/cli/packages/contentstack] Current
working directory
-p, --port=<value> [default: 3000] Port number

DESCRIPTION
Expand Down
Loading
Loading