@contentstack/cli-cm-export-query 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Contentstack
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,108 @@
1
+ # Contentstack CLI Query Export Plugin
2
+
3
+ A powerful CLI plugin for Contentstack that enables query-based content export with intelligent dependency resolution and asset reference detection.
4
+
5
+ ## Overview
6
+
7
+ This plugin extends the Contentstack CLI to export content based on custom queries, automatically resolving dependencies between content types, global fields, extensions, and taxonomies. It intelligently detects and exports referenced assets to ensure complete content portability.
8
+
9
+ ## Features
10
+
11
+ - 🔍 **Query-based Export**: Export content using custom queries instead of entire content types
12
+ - 🔗 **Dependency Resolution**: Automatically resolve and export dependencies (global fields, extensions, taxonomies)
13
+ - 🖼️ **Asset Reference Detection**: Intelligent detection of asset references in various formats
14
+ - 📁 **Organized Output**: Well-structured export with separate folders for each module
15
+ - ⚙️ **Configurable**: Support for external config files and flexible options
16
+ - 🌐 **Multi-locale Support**: Export content across different locales
17
+ - 📊 **Export Metadata**: Comprehensive metadata tracking for export operations
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ # Install as a Contentstack CLI plugin
23
+ npm install -g @contentstack/cli-cm-export-query
24
+
25
+ # Or install locally
26
+ npm install @contentstack/cli-cm-export-query
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ### Basic Export
32
+
33
+ ```bash
34
+ # Export using management token alias
35
+ csdx cm:stacks:export-query -a <alias> -q "{'title': {'$exists': true}}"
36
+
37
+ # Export using API key and management token
38
+ csdx cm:stacks:export-query --stack-api-key <api-key> -A <management-token> -q "{'title': {'$exists': true}}"
39
+ ```
40
+
41
+ ### Command Options
42
+
43
+ | Flag | Description | Required |
44
+ |------|-------------|----------|
45
+ | `-a, --alias` | Management token alias | Yes (or use -A) |
46
+ | `-A, --management-token` | Management token | Yes (or use -a) |
47
+ | `--stack-api-key` | Stack API key | Yes |
48
+ | `-q, --query` | Query for content export | Yes |
49
+ | `-d, --data-dir` | Export directory path | No |
50
+ | `--branch` | Branch name | No |
51
+ | `--skip-references` | Skip reference resolution | No |
52
+ | `--skip-dependencies` | Skip dependency export | No |
53
+ | `--secured-assets` | Include secured assets | No |
54
+ | `--config` | External config file path | No |
55
+
56
+ ### Query Examples
57
+
58
+ **Basic Content Query:**
59
+ ```bash
60
+ csdx cm:stacks:export-query -a prod -q "{'title': {'$regex': 'blog'}}"
61
+ ```
62
+
63
+ **Date Range Query:**
64
+ ```bash
65
+ csdx cm:stacks:export-query -a prod -q "{'updated_at': {'$gte': '2024-01-01'}}"
66
+ ```
67
+
68
+ **Complex Query:**
69
+ ```bash
70
+ csdx cm:stacks:export-query -a prod -q "{'$and': [{'title': {'$exists': true}}, {'tags': {'$in': ['featured']}}]}"
71
+ ```
72
+
73
+ ## Configuration
74
+
75
+ ### Default Configuration
76
+
77
+ The plugin includes a default configuration file at `src/config/export-defaults.json`:
78
+
79
+ ```json
80
+ {
81
+ "skipReferences": false,
82
+ "skipDependencies": false,
83
+ "securedAssets": false,
84
+ "includeGlobalFieldSchema": true,
85
+ "includePublishDetails": true,
86
+ "includeDimension": false,
87
+ "fetchConcurrency": 5,
88
+ "writeConcurrency": 5,
89
+ "batchSize": 100
90
+ }
91
+ ```
92
+
93
+ ### External Configuration
94
+
95
+ Create a custom config file and pass it using the `--config` flag:
96
+
97
+ ```json
98
+ {
99
+ "skipReferences": true,
100
+ "batchSize": 50,
101
+ "fetchConcurrency": 3,
102
+ "securedAssets": true
103
+ }
104
+ ```
105
+
106
+ ```bash
107
+ csdx cm:stacks:export-query -a prod -q "{'title': {'$exists': true}}" --config ./my-config.json
108
+ ```
@@ -0,0 +1,11 @@
1
+ import { Command } from '@contentstack/cli-command';
2
+ import { FlagInput } from '@contentstack/cli-utilities';
3
+ export default class ExportQueryCommand extends Command {
4
+ static description: string;
5
+ private exportDir;
6
+ static examples: string[];
7
+ static usage: string;
8
+ static flags: FlagInput;
9
+ static aliases: string[];
10
+ run(): Promise<void>;
11
+ }
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const cli_command_1 = require("@contentstack/cli-command");
4
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
5
+ const query_executor_1 = require("../../../core/query-executor");
6
+ const utils_1 = require("../../../utils");
7
+ class ExportQueryCommand extends cli_command_1.Command {
8
+ async run() {
9
+ try {
10
+ const { flags } = await this.parse(ExportQueryCommand);
11
+ // Setup export configuration
12
+ const exportQueryConfig = await (0, utils_1.setupQueryExportConfig)(flags);
13
+ exportQueryConfig.host = this.cmaHost;
14
+ exportQueryConfig.region = this.region;
15
+ if (this.developerHubUrl) {
16
+ exportQueryConfig.developerHubBaseUrl = this.developerHubUrl;
17
+ }
18
+ this.exportDir = (0, cli_utilities_1.sanitizePath)(exportQueryConfig.exportDir);
19
+ // Initialize and run query export
20
+ const managementAPIClient = await (0, cli_utilities_1.managementSDKClient)(exportQueryConfig);
21
+ const queryExporter = new query_executor_1.QueryExporter(managementAPIClient, exportQueryConfig);
22
+ await queryExporter.execute();
23
+ (0, utils_1.log)(exportQueryConfig, 'Query-based export completed successfully!', 'success');
24
+ (0, utils_1.log)(exportQueryConfig, `Export files saved to: ${this.exportDir}`, 'info');
25
+ }
26
+ catch (error) {
27
+ (0, utils_1.log)({ exportDir: this.exportDir }, `Export failed: ${(0, cli_utilities_1.formatError)(error)}`, 'error');
28
+ throw error;
29
+ }
30
+ }
31
+ }
32
+ exports.default = ExportQueryCommand;
33
+ ExportQueryCommand.description = 'Export content from a stack using query-based filtering';
34
+ ExportQueryCommand.examples = [
35
+ 'csdx cm:stacks:export-query --query \'{"modules":{"content-types":{"title":{"$in":["Blog","Author"]}}}}\'',
36
+ 'csdx cm:stacks:export-query --query ./ct-query.json --skip-references',
37
+ 'csdx cm:stacks:export-query --alias <alias> --query \'{"modules":{"entries":{"content_type_uid":"blog"}}}\'',
38
+ 'csdx cm:stacks:export-query --query \'{"modules":{"assets":{"title":{"$regex":"image"}}}}\'',
39
+ ];
40
+ ExportQueryCommand.usage = 'cm:stacks:export-query --query <value> [options]';
41
+ ExportQueryCommand.flags = {
42
+ config: cli_utilities_1.flags.string({
43
+ char: 'c',
44
+ description: 'Path to the configuration file',
45
+ }),
46
+ 'stack-api-key': cli_utilities_1.flags.string({
47
+ char: 'k',
48
+ description: 'Stack API key',
49
+ }),
50
+ 'data-dir': cli_utilities_1.flags.string({
51
+ char: 'd',
52
+ description: 'Path to store exported content',
53
+ }),
54
+ alias: cli_utilities_1.flags.string({
55
+ char: 'a',
56
+ description: 'Management token alias',
57
+ }),
58
+ branch: cli_utilities_1.flags.string({
59
+ description: 'Branch name to export from',
60
+ }),
61
+ query: cli_utilities_1.flags.string({
62
+ required: true,
63
+ description: 'Query as JSON string or file path',
64
+ }),
65
+ 'skip-references': cli_utilities_1.flags.boolean({
66
+ description: 'Skip referenced content types',
67
+ }),
68
+ 'skip-dependencies': cli_utilities_1.flags.boolean({
69
+ description: 'Skip dependent modules (global-fields, extensions, taxonomies)',
70
+ }),
71
+ 'secured-assets': cli_utilities_1.flags.boolean({
72
+ description: 'Export secured assets',
73
+ }),
74
+ yes: cli_utilities_1.flags.boolean({
75
+ char: 'y',
76
+ description: 'Skip confirmation prompts',
77
+ }),
78
+ };
79
+ ExportQueryCommand.aliases = ['cm:export-query'];
@@ -0,0 +1 @@
1
+ { "skipDependencies": true, "skipStackSettings": false, "personalizationEnabled": true }
@@ -0,0 +1,3 @@
1
+ import { DefaultConfig } from '../types';
2
+ declare const config: DefaultConfig;
3
+ export default config;
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config = {
4
+ contentVersion: 2,
5
+ host: 'https://api.contentstack.io/v3',
6
+ // Query-based export module configuration
7
+ modules: {
8
+ // Always export - general modules
9
+ general: ['stack', 'locales', 'environments'],
10
+ // Query target modules
11
+ queryable: ['content-types'],
12
+ dependent: ['global-fields', 'extensions', 'marketplace-apps', 'taxonomies', 'personalize'],
13
+ // Content modules
14
+ content: ['entries', 'assets'],
15
+ // Export order based on dependencies
16
+ exportOrder: [
17
+ 'stack',
18
+ 'locales',
19
+ 'environments',
20
+ 'content-types',
21
+ 'global-fields',
22
+ 'extensions',
23
+ 'taxonomies',
24
+ 'entries',
25
+ 'assets',
26
+ ],
27
+ },
28
+ // Query-specific settings
29
+ queryConfig: {
30
+ maxRecursionDepth: 10,
31
+ batchSize: 100,
32
+ metadataFileName: '_query-meta.json',
33
+ validation: {
34
+ maxQueryDepth: 5,
35
+ maxArraySize: 1000,
36
+ allowedDateFormats: ['ISO8601', 'YYYY-MM-DD', 'MM/DD/YYYY'],
37
+ },
38
+ },
39
+ // API endpoints
40
+ apis: {
41
+ stacks: '/stacks/',
42
+ locales: '/locales/',
43
+ environments: '/environments/',
44
+ content_types: '/content_types/',
45
+ global_fields: '/global_fields/',
46
+ extensions: '/extensions/',
47
+ taxonomies: '/taxonomies/',
48
+ entries: '/entries/',
49
+ assets: '/assets/',
50
+ },
51
+ // Performance settings
52
+ fetchConcurrency: 5,
53
+ writeConcurrency: 5,
54
+ maxCTReferenceDepth: 20,
55
+ // Optional settings
56
+ };
57
+ exports.default = config;
@@ -0,0 +1,59 @@
1
+ import { DefaultConfig } from '../types';
2
+
3
+ const config: DefaultConfig = {
4
+ contentVersion: 2,
5
+ host: 'https://api.contentstack.io/v3',
6
+
7
+ // Query-based export module configuration
8
+ modules: {
9
+ // Always export - general modules
10
+ general: ['stack', 'locales', 'environments'],
11
+ // Query target modules
12
+ queryable: ['content-types'],
13
+ dependent: ['global-fields', 'extensions', 'marketplace-apps', 'taxonomies', 'personalize'],
14
+ // Content modules
15
+ content: ['entries', 'assets'],
16
+ // Export order based on dependencies
17
+ exportOrder: [
18
+ 'stack',
19
+ 'locales',
20
+ 'environments',
21
+ 'content-types',
22
+ 'global-fields',
23
+ 'extensions',
24
+ 'taxonomies',
25
+ 'entries',
26
+ 'assets',
27
+ ],
28
+ },
29
+ // Query-specific settings
30
+ queryConfig: {
31
+ maxRecursionDepth: 10,
32
+ batchSize: 100,
33
+ metadataFileName: '_query-meta.json',
34
+ validation: {
35
+ maxQueryDepth: 5,
36
+ maxArraySize: 1000,
37
+ allowedDateFormats: ['ISO8601', 'YYYY-MM-DD', 'MM/DD/YYYY'],
38
+ },
39
+ },
40
+ // API endpoints
41
+ apis: {
42
+ stacks: '/stacks/',
43
+ locales: '/locales/',
44
+ environments: '/environments/',
45
+ content_types: '/content_types/',
46
+ global_fields: '/global_fields/',
47
+ extensions: '/extensions/',
48
+ taxonomies: '/taxonomies/',
49
+ entries: '/entries/',
50
+ assets: '/assets/',
51
+ },
52
+ // Performance settings
53
+ fetchConcurrency: 5,
54
+ writeConcurrency: 5,
55
+ maxCTReferenceDepth: 20,
56
+ // Optional settings
57
+ };
58
+
59
+ export default config;
@@ -0,0 +1,11 @@
1
+ import { QueryExportConfig, Modules, ExportOptions } from '../types';
2
+ export declare class ModuleExporter {
3
+ private exportQueryConfig;
4
+ private exportedModules;
5
+ constructor(exportQueryConfig: QueryExportConfig);
6
+ exportModule(moduleName: Modules, options?: ExportOptions): Promise<void>;
7
+ /**
8
+ * Build export command arguments based on module and options
9
+ */
10
+ private buildExportCommand;
11
+ }
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModuleExporter = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
6
+ const cli_cm_export_1 = tslib_1.__importDefault(require("@contentstack/cli-cm-export"));
7
+ const logger_1 = require("../utils/logger");
8
+ class ModuleExporter {
9
+ constructor(exportQueryConfig) {
10
+ this.exportedModules = [];
11
+ this.exportQueryConfig = exportQueryConfig;
12
+ }
13
+ async exportModule(moduleName, options = {}) {
14
+ try {
15
+ (0, logger_1.log)(this.exportQueryConfig, `Exporting module: ${moduleName}`, 'info');
16
+ // Build command arguments
17
+ const cmd = this.buildExportCommand(moduleName, options);
18
+ (0, logger_1.log)(this.exportQueryConfig, `Running export command: ${cmd.join(' ')}`, 'debug');
19
+ // Configurable delay
20
+ const delay = this.exportQueryConfig.exportDelayMs || 2000;
21
+ await new Promise((resolve) => setTimeout(resolve, delay));
22
+ // Create export command instance
23
+ await cli_cm_export_1.default.run(cmd);
24
+ // Read the exported data
25
+ // const data = await this.readExportedData(moduleName, options);
26
+ if (!this.exportedModules.includes(moduleName)) {
27
+ this.exportedModules.push(moduleName);
28
+ }
29
+ // success message
30
+ (0, logger_1.log)(this.exportQueryConfig, `Successfully exported ${moduleName}`, 'success');
31
+ }
32
+ catch (error) {
33
+ (0, logger_1.log)(this.exportQueryConfig, `Failed to export ${moduleName}: ${(0, cli_utilities_1.formatError)(error)}`, 'error');
34
+ throw error;
35
+ }
36
+ }
37
+ /**
38
+ * Build export command arguments based on module and options
39
+ */
40
+ buildExportCommand(moduleName, options) {
41
+ const cmd = [];
42
+ // Stack API key (required)
43
+ cmd.push('-k', this.exportQueryConfig.stackApiKey);
44
+ // Directory
45
+ const directory = options.directory || this.exportQueryConfig.exportDir;
46
+ cmd.push('-d', directory);
47
+ // Module
48
+ cmd.push('--module', moduleName);
49
+ // Alias (management token)
50
+ if (options.alias) {
51
+ cmd.push('-a', options.alias);
52
+ }
53
+ // Branch
54
+ if (options.branch || this.exportQueryConfig.branchName) {
55
+ cmd.push('--branch', options.branch || this.exportQueryConfig.branchName);
56
+ }
57
+ // Query (if provided)
58
+ if (options.query) {
59
+ cmd.push('--query', JSON.stringify(options.query));
60
+ }
61
+ // Secured assets
62
+ if (options.securedAssets || this.exportQueryConfig.securedAssets) {
63
+ cmd.push('--secured-assets');
64
+ }
65
+ // External config file
66
+ const externalConfigPath = options.configPath || this.exportQueryConfig.externalConfigPath;
67
+ if (externalConfigPath) {
68
+ cmd.push('--config', externalConfigPath);
69
+ }
70
+ // Auto confirm
71
+ cmd.push('-y');
72
+ return cmd;
73
+ }
74
+ }
75
+ exports.ModuleExporter = ModuleExporter;
@@ -0,0 +1,17 @@
1
+ import { ContentstackClient } from '@contentstack/cli-utilities';
2
+ import { QueryExportConfig } from '../types';
3
+ export declare class QueryExporter {
4
+ private stackAPIClient;
5
+ private exportQueryConfig;
6
+ private queryParser;
7
+ private moduleExporter;
8
+ constructor(managementAPIClient: ContentstackClient, exportQueryConfig: QueryExportConfig);
9
+ execute(): Promise<void>;
10
+ private exportGeneralModules;
11
+ private exportQueriedModule;
12
+ private exportReferencedContentTypes;
13
+ private exportDependentModules;
14
+ private exportContentModules;
15
+ private exportEntries;
16
+ private exportReferencedAssets;
17
+ }