diff --git a/package-lock.json b/package-lock.json index cb4e517c58..8c1d9f8826 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5159,6 +5159,14 @@ "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==" }, + "node_modules/cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", @@ -7476,6 +7484,14 @@ "node": ">=0.6.0" } }, + "node_modules/eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==", + "engines": { + "node": "> 0.1.90" + } + }, "node_modules/fancy-test": { "version": "1.4.10", "resolved": "https://registry.npmjs.org/fancy-test/-/fancy-test-1.4.10.tgz", @@ -9964,6 +9980,11 @@ "whatwg-fetch": "^3.4.1" } }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", @@ -15033,6 +15054,50 @@ "node": ">=10" } }, + "node_modules/prompt": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", + "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==", + "dependencies": { + "@colors/colors": "1.5.0", + "async": "3.2.3", + "read": "1.0.x", + "revalidator": "0.1.x", + "winston": "2.x" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/prompt/node_modules/async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" + }, + "node_modules/prompt/node_modules/winston": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", + "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", + "dependencies": { + "async": "^2.6.4", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "stack-trace": "0.0.x" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/prompt/node_modules/winston/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -15232,6 +15297,17 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/read-cmd-shim": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-3.0.1.tgz", @@ -15920,6 +15996,14 @@ "node": ">=0.10.0" } }, + "node_modules/revalidator": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -19968,24 +20052,24 @@ }, "packages/contentstack": { "name": "@contentstack/cli", - "version": "1.7.6", + "version": "1.7.7", "license": "MIT", "dependencies": { - "@contentstack/cli-auth": "^1.3.8", - "@contentstack/cli-cm-bootstrap": "^1.4.8", - "@contentstack/cli-cm-branches": "^1.0.5", - "@contentstack/cli-cm-bulk-publish": "^1.3.7", - "@contentstack/cli-cm-clone": "^1.4.8", - "@contentstack/cli-cm-export": "^1.5.8", - "@contentstack/cli-cm-export-to-csv": "^1.3.8", - "@contentstack/cli-cm-import": "^1.5.8", - "@contentstack/cli-cm-migrate-rte": "^1.4.7", - "@contentstack/cli-cm-seed": "^1.4.8", - "@contentstack/cli-command": "^1.2.8", + "@contentstack/cli-auth": "^1.3.9", + "@contentstack/cli-cm-bootstrap": "^1.4.9", + "@contentstack/cli-cm-branches": "^1.0.6", + "@contentstack/cli-cm-bulk-publish": "^1.3.8", + "@contentstack/cli-cm-clone": "^1.4.9", + "@contentstack/cli-cm-export": "^1.5.9", + "@contentstack/cli-cm-export-to-csv": "^1.3.9", + "@contentstack/cli-cm-import": "^1.5.9", + "@contentstack/cli-cm-migrate-rte": "^1.4.8", + "@contentstack/cli-cm-seed": "^1.4.9", + "@contentstack/cli-command": "^1.2.9", "@contentstack/cli-config": "^1.4.6", - "@contentstack/cli-launch": "^1.0.5", - "@contentstack/cli-migration": "^1.3.7", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-launch": "^1.0.6", + "@contentstack/cli-migration": "^1.3.8", + "@contentstack/cli-utilities": "^1.4.5", "@contentstack/management": "^1.8.0", "@oclif/plugin-help": "^5", "@oclif/plugin-not-found": "^2.3.9", @@ -20033,11 +20117,11 @@ }, "packages/contentstack-auth": { "name": "@contentstack/cli-auth", - "version": "1.3.8", + "version": "1.3.9", "license": "MIT", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "chalk": "^4.0.0", "debug": "^4.1.1", "inquirer": "8.2.4", @@ -20224,12 +20308,12 @@ }, "packages/contentstack-bootstrap": { "name": "@contentstack/cli-cm-bootstrap", - "version": "1.4.8", + "version": "1.4.9", "license": "MIT", "dependencies": { - "@contentstack/cli-cm-seed": "^1.4.8", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-cm-seed": "^1.4.9", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "inquirer": "8.2.4", "mkdirp": "^1.0.4", "tar": "^6.1.13" @@ -20303,11 +20387,11 @@ }, "packages/contentstack-branches": { "name": "@contentstack/cli-cm-branches", - "version": "1.0.5", + "version": "1.0.6", "license": "MIT", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/command": "^1.8.16", "@oclif/config": "^1.18.3", "@oclif/core": "^2.3.0", @@ -20516,11 +20600,11 @@ }, "packages/contentstack-bulk-publish": { "name": "@contentstack/cli-cm-bulk-publish", - "version": "1.3.7", + "version": "1.3.8", "license": "MIT", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "bluebird": "^3.7.2", "chalk": "^4.1.2", "inquirer": "8.2.4", @@ -20563,19 +20647,21 @@ }, "packages/contentstack-clone": { "name": "@contentstack/cli-cm-clone", - "version": "1.4.8", + "version": "1.4.9", "license": "MIT", "dependencies": { - "@contentstack/cli-cm-export": "^1.5.8", - "@contentstack/cli-cm-import": "^1.5.8", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@colors/colors": "^1.5.0", + "@contentstack/cli-cm-export": "^1.5.9", + "@contentstack/cli-cm-import": "^1.5.9", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "async": "^3.2.4", "chalk": "^4.1.0", "child_process": "^1.0.2", "fancy-test": "^1.4.10", "inquirer": "8.2.4", "ora": "^5.1.0", + "prompt": "^1.3.0", "rimraf": "^3.0.2", "winston": "^3.7.2" }, @@ -20623,10 +20709,10 @@ }, "packages/contentstack-command": { "name": "@contentstack/cli-command", - "version": "1.2.8", + "version": "1.2.9", "license": "MIT", "dependencies": { - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-utilities": "^1.4.5", "contentstack": "^3.10.1" }, "devDependencies": { @@ -20847,11 +20933,11 @@ }, "packages/contentstack-config": { "name": "@contentstack/cli-config", - "version": "1.4.6", + "version": "1.4.7", "license": "MIT", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "chalk": "^4.0.0", "debug": "^4.1.1", "inquirer": "8.2.4", @@ -21073,11 +21159,11 @@ }, "packages/contentstack-export": { "name": "@contentstack/cli-cm-export", - "version": "1.5.8", + "version": "1.5.9", "license": "MIT", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/command": "^1.8.16", "@oclif/config": "^1.18.3", "async": "^3.2.4", @@ -21117,11 +21203,11 @@ }, "packages/contentstack-export-to-csv": { "name": "@contentstack/cli-cm-export-to-csv", - "version": "1.3.8", + "version": "1.3.9", "license": "MIT", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "chalk": "^4.1.0", "fast-csv": "^4.3.6", "inquirer": "8.2.4", @@ -21321,11 +21407,11 @@ }, "packages/contentstack-import": { "name": "@contentstack/cli-cm-import", - "version": "1.5.8", + "version": "1.5.9", "license": "MIT", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/config": "^1.18.3", "big-json": "^3.2.0", "bluebird": "^3.7.2", @@ -21366,12 +21452,12 @@ }, "packages/contentstack-launch": { "name": "@contentstack/cli-launch", - "version": "1.0.5", + "version": "1.0.6", "license": "MIT", "dependencies": { "@apollo/client": "^3.7.9", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/plugin-help": "^5", "@oclif/plugin-plugins": "^2.3.2", "@types/express": "^4.17.17", @@ -21774,11 +21860,11 @@ }, "packages/contentstack-migrate-rte": { "name": "@contentstack/cli-cm-migrate-rte", - "version": "1.4.7", + "version": "1.4.8", "license": "MIT", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@contentstack/json-rte-serializer": "^2.0.2", "chalk": "^4.1.2", "collapse-whitespace": "^1.1.7", @@ -21813,11 +21899,11 @@ }, "packages/contentstack-migration": { "name": "@contentstack/cli-migration", - "version": "1.3.7", + "version": "1.3.8", "license": "MIT", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/command": "^1.8.16", "@oclif/config": "^1.18.3", "async": "^3.2.4", @@ -21849,12 +21935,12 @@ }, "packages/contentstack-seed": { "name": "@contentstack/cli-cm-seed", - "version": "1.4.8", + "version": "1.4.9", "license": "MIT", "dependencies": { - "@contentstack/cli-cm-import": "^1.5.8", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-cm-import": "^1.5.9", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "axios": "1.3.4", "inquirer": "8.2.4", "mkdirp": "^1.0.4", @@ -21930,7 +22016,7 @@ }, "packages/contentstack-utilities": { "name": "@contentstack/cli-utilities", - "version": "1.4.4", + "version": "1.4.5", "license": "MIT", "dependencies": { "@contentstack/management": "^1.8.0", @@ -23802,21 +23888,21 @@ "@contentstack/cli": { "version": "file:packages/contentstack", "requires": { - "@contentstack/cli-auth": "^1.3.8", - "@contentstack/cli-cm-bootstrap": "^1.4.8", - "@contentstack/cli-cm-branches": "^1.0.5", - "@contentstack/cli-cm-bulk-publish": "^1.3.7", - "@contentstack/cli-cm-clone": "^1.4.8", - "@contentstack/cli-cm-export": "^1.5.8", - "@contentstack/cli-cm-export-to-csv": "^1.3.8", - "@contentstack/cli-cm-import": "^1.5.8", - "@contentstack/cli-cm-migrate-rte": "^1.4.7", - "@contentstack/cli-cm-seed": "^1.4.8", - "@contentstack/cli-command": "^1.2.8", + "@contentstack/cli-auth": "^1.3.9", + "@contentstack/cli-cm-bootstrap": "^1.4.9", + "@contentstack/cli-cm-branches": "^1.0.6", + "@contentstack/cli-cm-bulk-publish": "^1.3.8", + "@contentstack/cli-cm-clone": "^1.4.9", + "@contentstack/cli-cm-export": "^1.5.9", + "@contentstack/cli-cm-export-to-csv": "^1.3.9", + "@contentstack/cli-cm-import": "^1.5.9", + "@contentstack/cli-cm-migrate-rte": "^1.4.8", + "@contentstack/cli-cm-seed": "^1.4.9", + "@contentstack/cli-command": "^1.2.9", "@contentstack/cli-config": "^1.4.6", - "@contentstack/cli-launch": "^1.0.5", - "@contentstack/cli-migration": "^1.3.7", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-launch": "^1.0.6", + "@contentstack/cli-migration": "^1.3.8", + "@contentstack/cli-utilities": "^1.4.5", "@contentstack/management": "^1.8.0", "@oclif/plugin-help": "^5", "@oclif/plugin-not-found": "^2.3.9", @@ -23857,8 +23943,8 @@ "@contentstack/cli-auth": { "version": "file:packages/contentstack-auth", "requires": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@fancy-test/nock": "^0.1.1", "@oclif/plugin-help": "^5.1.19", "@oclif/test": "^2.2.10", @@ -24013,9 +24099,9 @@ "@contentstack/cli-cm-bootstrap": { "version": "file:packages/contentstack-bootstrap", "requires": { - "@contentstack/cli-cm-seed": "^1.4.8", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-cm-seed": "^1.4.9", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/test": "^2.2.10", "@types/inquirer": "^9.0.3", "@types/mkdirp": "^1.0.1", @@ -24073,10 +24159,10 @@ "version": "file:packages/contentstack-branches", "requires": { "@contentstack/cli-auth": "^1.3.8", - "@contentstack/cli-command": "^1.2.8", + "@contentstack/cli-command": "^1.2.9", "@contentstack/cli-config": "^1.4.6", "@contentstack/cli-dev-dependencies": "^1.2.3", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/command": "^1.8.16", "@oclif/config": "^1.18.3", "@oclif/core": "^2.3.0", @@ -24247,8 +24333,8 @@ "@contentstack/cli-cm-bulk-publish": { "version": "file:packages/contentstack-bulk-publish", "requires": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/test": "^1.2.6", "bluebird": "^3.7.2", "chai": "^4.2.0", @@ -24286,10 +24372,11 @@ "@contentstack/cli-cm-clone": { "version": "file:packages/contentstack-clone", "requires": { - "@contentstack/cli-cm-export": "^1.5.8", - "@contentstack/cli-cm-import": "^1.5.8", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@colors/colors": "^1.5.0", + "@contentstack/cli-cm-export": "^1.5.9", + "@contentstack/cli-cm-import": "^1.5.9", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/test": "^1.2.7", "async": "^3.2.4", "chai": "^4.2.0", @@ -24305,6 +24392,7 @@ "nyc": "^15.1.0", "oclif": "^3.8.1", "ora": "^5.1.0", + "prompt": "^1.3.0", "rimraf": "^3.0.2", "sinon": "^15.0.1", "winston": "^3.7.2" @@ -24333,10 +24421,10 @@ "version": "file:packages/contentstack-export", "requires": { "@contentstack/cli-auth": "^1.3.8", - "@contentstack/cli-command": "^1.2.8", + "@contentstack/cli-command": "^1.2.9", "@contentstack/cli-config": "^1.4.6", "@contentstack/cli-dev-dependencies": "^1.2.3", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/command": "^1.8.16", "@oclif/config": "^1.18.3", "@oclif/plugin-help": "^5.1.19", @@ -24505,8 +24593,8 @@ "@contentstack/cli-cm-export-to-csv": { "version": "file:packages/contentstack-export-to-csv", "requires": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/test": "^2.2.10", "chai": "^4.2.0", "chalk": "^4.1.0", @@ -24526,8 +24614,8 @@ "@contentstack/cli-cm-import": { "version": "file:packages/contentstack-import", "requires": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/config": "^1.18.3", "@oclif/test": "^1.2.6", "big-json": "^3.2.0", @@ -24563,8 +24651,8 @@ "@contentstack/cli-cm-migrate-rte": { "version": "file:packages/contentstack-migrate-rte", "requires": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@contentstack/json-rte-serializer": "^2.0.2", "@oclif/test": "^2.2.10", "chai": "^4.3.4", @@ -24597,9 +24685,9 @@ "@contentstack/cli-cm-seed": { "version": "file:packages/contentstack-seed", "requires": { - "@contentstack/cli-cm-import": "^1.5.8", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-cm-import": "^1.5.9", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/plugin-help": "^5.1.19", "@types/inquirer": "^9.0.3", "@types/jest": "^26.0.15", @@ -24658,7 +24746,7 @@ "@contentstack/cli-command": { "version": "file:packages/contentstack-command", "requires": { - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/test": "^2.2.10", "@types/chai": "^4.2.18", "@types/mkdirp": "^1.0.1", @@ -24834,8 +24922,8 @@ "@contentstack/cli-config": { "version": "file:packages/contentstack-config", "requires": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/test": "^2.2.10", "@types/chai": "^4.2.18", "@types/inquirer": "^9.0.3", @@ -25021,8 +25109,8 @@ "version": "file:packages/contentstack-launch", "requires": { "@apollo/client": "^3.7.9", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/plugin-help": "^5", "@oclif/plugin-plugins": "^2.3.2", "@oclif/test": "^2.3.6", @@ -25316,8 +25404,8 @@ "@contentstack/cli-migration": { "version": "file:packages/contentstack-migration", "requires": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/command": "^1.8.16", "@oclif/config": "^1.18.3", "@oclif/test": "^2.2.10", @@ -29923,6 +30011,11 @@ } } }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha512-TVF6svNzeQCOpjCqsy0/CSy8VgObG3wXusJ73xW2GbG5rGx7lC8zxDSURicsXI2UsGdi2L0QNRCi745/wUDvsA==" + }, "dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", @@ -31652,6 +31745,11 @@ } } }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ==" + }, "fancy-test": { "version": "1.4.10", "resolved": "https://registry.npmjs.org/fancy-test/-/fancy-test-1.4.10.tgz", @@ -33512,6 +33610,11 @@ "whatwg-fetch": "^3.4.1" } }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==" + }, "istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", @@ -37484,6 +37587,48 @@ "retry": "^0.12.0" } }, + "prompt": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/prompt/-/prompt-1.3.0.tgz", + "integrity": "sha512-ZkaRWtaLBZl7KKAKndKYUL8WqNT+cQHKRZnT4RYYms48jQkFw3rrBL+/N5K/KtdEveHkxs982MX2BkDKub2ZMg==", + "requires": { + "@colors/colors": "1.5.0", + "async": "3.2.3", + "read": "1.0.x", + "revalidator": "0.1.x", + "winston": "2.x" + }, + "dependencies": { + "async": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" + }, + "winston": { + "version": "2.4.7", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.7.tgz", + "integrity": "sha512-vLB4BqzCKDnnZH9PHGoS2ycawueX4HLqENXQitvFHczhgW2vFpSOn31LZtVr1KU8YTw7DS4tM+cqyovxo8taVg==", + "requires": { + "async": "^2.6.4", + "colors": "1.0.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "isstream": "0.1.x", + "stack-trace": "0.0.x" + }, + "dependencies": { + "async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "requires": { + "lodash": "^4.17.14" + } + } + } + } + } + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -37625,6 +37770,14 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "requires": { + "mute-stream": "~0.0.4" + } + }, "read-cmd-shim": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/read-cmd-shim/-/read-cmd-shim-3.0.1.tgz", @@ -38145,6 +38298,11 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" }, + "revalidator": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/revalidator/-/revalidator-0.1.8.tgz", + "integrity": "sha512-xcBILK2pA9oh4SiinPEZfhP8HfrB/ha+a2fTMyl7Om2WjlDVrOQy99N2MXXlUHqGJz4qEu2duXxHJjDWuK/0xg==" + }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", diff --git a/packages/contentstack-auth/README.md b/packages/contentstack-auth/README.md index 7d1303d3df..c478130f0e 100644 --- a/packages/contentstack-auth/README.md +++ b/packages/contentstack-auth/README.md @@ -18,7 +18,7 @@ $ npm install -g @contentstack/cli-auth $ csdx COMMAND running command... $ csdx (--version) -@contentstack/cli-auth/1.3.8 darwin-x64 node-v18.16.0 +@contentstack/cli-auth/1.3.9 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-auth/package.json b/packages/contentstack-auth/package.json index 84aa692492..8d08e3a267 100644 --- a/packages/contentstack-auth/package.json +++ b/packages/contentstack-auth/package.json @@ -1,7 +1,7 @@ { "name": "@contentstack/cli-auth", "description": "Contentstack CLI plugin for authentication activities", - "version": "1.3.8", + "version": "1.3.9", "author": "Contentstack", "bugs": "https://github.com/contentstack/cli/issues", "scripts": { @@ -21,8 +21,8 @@ "test:unit": "mocha --forbid-only \"test/unit/*.test.ts\"" }, "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "chalk": "^4.0.0", "debug": "^4.1.1", "inquirer": "8.2.4", diff --git a/packages/contentstack-bootstrap/README.md b/packages/contentstack-bootstrap/README.md index 2f306e9069..c2c8c03777 100644 --- a/packages/contentstack-bootstrap/README.md +++ b/packages/contentstack-bootstrap/README.md @@ -15,7 +15,7 @@ $ npm install -g @contentstack/cli-cm-bootstrap $ csdx COMMAND running command... $ csdx (--version) -@contentstack/cli-cm-bootstrap/1.4.8 darwin-x64 node-v18.16.0 +@contentstack/cli-cm-bootstrap/1.4.9 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-bootstrap/package.json b/packages/contentstack-bootstrap/package.json index 631b996d16..cadf532e24 100644 --- a/packages/contentstack-bootstrap/package.json +++ b/packages/contentstack-bootstrap/package.json @@ -1,7 +1,7 @@ { "name": "@contentstack/cli-cm-bootstrap", "description": "Bootstrap contentstack apps", - "version": "1.4.8", + "version": "1.4.9", "author": "Contentstack", "bugs": "https://github.com/contentstack/cli/issues", "scripts": { @@ -17,9 +17,9 @@ "test:report": "nyc --reporter=lcov mocha \"test/**/*.test.js\"" }, "dependencies": { - "@contentstack/cli-cm-seed": "^1.4.8", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-cm-seed": "^1.4.9", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "inquirer": "8.2.4", "mkdirp": "^1.0.4", "tar": "^6.1.13" diff --git a/packages/contentstack-branches/README.md b/packages/contentstack-branches/README.md index 7b108f7d17..3756657833 100755 --- a/packages/contentstack-branches/README.md +++ b/packages/contentstack-branches/README.md @@ -38,7 +38,7 @@ $ npm install -g @contentstack/cli-cm-branches $ csdx COMMAND running command... $ csdx (--version) -@contentstack/cli-cm-branches/1.0.5 darwin-x64 node-v18.16.0 +@contentstack/cli-cm-branches/1.0.6 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-branches/package.json b/packages/contentstack-branches/package.json index d6d1c5bbb3..6d829ff215 100644 --- a/packages/contentstack-branches/package.json +++ b/packages/contentstack-branches/package.json @@ -1,12 +1,12 @@ { "name": "@contentstack/cli-cm-branches", "description": "Contentstack CLI plugin to do branches operations", - "version": "1.0.5", + "version": "1.0.6", "author": "Contentstack", "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/command": "^1.8.16", "@oclif/config": "^1.18.3", "@oclif/core": "^2.3.0", diff --git a/packages/contentstack-bulk-publish/README.md b/packages/contentstack-bulk-publish/README.md index 4d9488a896..7de57a81c3 100644 --- a/packages/contentstack-bulk-publish/README.md +++ b/packages/contentstack-bulk-publish/README.md @@ -18,7 +18,7 @@ $ npm install -g @contentstack/cli-cm-bulk-publish $ csdx COMMAND running command... $ csdx (--version) -@contentstack/cli-cm-bulk-publish/1.3.7 darwin-x64 node-v18.16.0 +@contentstack/cli-cm-bulk-publish/1.3.8 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-bulk-publish/package.json b/packages/contentstack-bulk-publish/package.json index 994690662a..02f49ca681 100644 --- a/packages/contentstack-bulk-publish/package.json +++ b/packages/contentstack-bulk-publish/package.json @@ -1,12 +1,12 @@ { "name": "@contentstack/cli-cm-bulk-publish", "description": "Contentstack CLI plugin for bulk publish actions", - "version": "1.3.7", + "version": "1.3.8", "author": "Contentstack", "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "bluebird": "^3.7.2", "chalk": "^4.1.2", "inquirer": "8.2.4", diff --git a/packages/contentstack-clone/README.md b/packages/contentstack-clone/README.md index bd23039390..0bd725b5bd 100644 --- a/packages/contentstack-clone/README.md +++ b/packages/contentstack-clone/README.md @@ -15,7 +15,7 @@ $ npm install -g @contentstack/cli-cm-clone $ csdx COMMAND running command... $ csdx (--version) -@contentstack/cli-cm-clone/1.4.8 darwin-x64 node-v18.16.0 +@contentstack/cli-cm-clone/1.4.9 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-clone/package.json b/packages/contentstack-clone/package.json index 780e247488..1e020cf778 100644 --- a/packages/contentstack-clone/package.json +++ b/packages/contentstack-clone/package.json @@ -1,20 +1,22 @@ { "name": "@contentstack/cli-cm-clone", "description": "Contentstack stack clone plugin", - "version": "1.4.8", + "version": "1.4.9", "author": "Contentstack", "bugs": "https://github.com/rohitmishra209/cli-cm-clone/issues", "dependencies": { - "@contentstack/cli-cm-export": "^1.5.8", - "@contentstack/cli-cm-import": "^1.5.8", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@colors/colors": "^1.5.0", + "@contentstack/cli-cm-export": "^1.5.9", + "@contentstack/cli-cm-import": "^1.5.9", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "async": "^3.2.4", "chalk": "^4.1.0", "child_process": "^1.0.2", "fancy-test": "^1.4.10", "inquirer": "8.2.4", "ora": "^5.1.0", + "prompt": "^1.3.0", "rimraf": "^3.0.2", "winston": "^3.7.2" }, diff --git a/packages/contentstack-clone/src/lib/util/clone-handler.js b/packages/contentstack-clone/src/lib/util/clone-handler.js index edae3917ed..7ea2057fda 100644 --- a/packages/contentstack-clone/src/lib/util/clone-handler.js +++ b/packages/contentstack-clone/src/lib/util/clone-handler.js @@ -1,12 +1,12 @@ const ora = require('ora'); const path = require('path'); const inquirer = require('inquirer'); -const rimraf = require('rimraf'); const chalk = require('chalk'); +const prompt = require('prompt'); +const colors = require('@colors/colors/safe'); let exportCmd = require('@contentstack/cli-cm-export'); let importCmd = require('@contentstack/cli-cm-import'); -const { CustomAbortController } = require('./abort-controller'); const { HandleOrgCommand, @@ -57,6 +57,16 @@ let structureList = [ ]; let master_locale; +// Overrides prompt's stop method +prompt.stop = function () { + if (prompt.stopped) { + return; + } + prompt.emit('stop'); + prompt.stopped = true; + return prompt; +}; + class CloneHandler { constructor(opt) { config = opt; @@ -124,7 +134,7 @@ class CloneHandler { let spinner; try { const stackAPIClient = client.stack({ - api_key: config.source_stack, + api_key: config.target_stack ? config.target_stack : config.source_stack, management_token: config.management_token, }); @@ -208,12 +218,6 @@ class CloneHandler { throw e; } } - setAbortController(abortController) { - this.abortController = abortController; - } - abort() { - this.abortController && this.abortController.abort(); - } displayBackOptionMessage() { const ui = new inquirer.ui.BottomBar(); ui.updateBottomBar(chalk.cyan('\nPress shift & left arrow together to undo the operation\n')); @@ -252,7 +256,6 @@ class CloneHandler { config.source_stack = null; config.sourceStackBranch = null; if (self.executingCommand != 0) { - self.abort(); console.clear(); await cloneCommand.undo(); } @@ -261,8 +264,7 @@ class CloneHandler { process.stdin.addListener('keypress', keyPressHandler); this.setBackKeyPressHandler(keyPressHandler); - const params = { org, isSource: true, msg: 'Select the source stack' }; - await this.executeStackPrompt(params); + await this.executeStackPrompt({ org, isSource: true, msg: 'Select the source stack' }); } else { return reject('Org not found.'); } @@ -312,7 +314,7 @@ class CloneHandler { await cloneCommand.execute(new SetBranchCommand(null, this)); if (exportRes) { - this.executeDestination().catch(() => reject()); + this.executeDestination().catch(() => { throw ''; }); } } catch (error) { throw error; @@ -323,61 +325,95 @@ class CloneHandler { async executeDestination() { return new Promise(async (resolve, reject) => { - let stackAbortController; + let keyPressHandler; try { - stackAbortController = new CustomAbortController(); - let canCreateStack = false; - if (!config.target_stack) { canCreateStack = await inquirer.prompt(stackCreationConfirmation); } this.setExectingCommand(0); - if (!canCreateStack.stackCreate) { - if (!config.target_stack) { - const orgMsg = 'Choose an organization where the destination stack exists: '; - const org = await cloneCommand.execute(new HandleOrgCommand({ msg: orgMsg }, this)); - - if (org) { - const stackMsg = 'Choose the destination stack:'; - await cloneCommand.execute( - new HandleDestinationStackCommand({ org, msg: stackMsg, stackAbortController, isSource: false }, this), - ); - } - } + this.removeBackKeyPressHandler(); - // NOTE GET list of branches if branches enabled - if (config.target_stack) { - await cloneCommand.execute( - new HandleBranchCommand({ isSource: false, api_key: config.target_stack }, this), - ); - } + const orgMsgExistingStack = 'Choose an organization where the destination stack exists: '; + const orgMsgNewStack = 'Choose an organization where you want to create a stack: '; + + let org; + if (!config.target_stack) { + org = await cloneCommand.execute(new HandleOrgCommand({ + msg: !canCreateStack.stackCreate ? orgMsgExistingStack : orgMsgNewStack + }, this)); + } + + const params = { org, canCreateStack }; + if (!config.target_stack) { + let self = this; + keyPressHandler = async function (_ch, key) { + if (key.name === 'left' && key.shift) { + if (self.executingCommand === 1) { + self.setExectingCommand(3); + } else if (self.executingCommand === 2) { + self.setExectingCommand(4); + } + if (self.createNewStackPrompt) { + self.createNewStackPrompt.stop(); + } + config.target_stack = null; + config.targetStackBranch = null; + if (self.executingCommand != 0) { + console.clear(); + await cloneCommand.undo(); + } + } + }; + process.stdin.addListener('keypress', keyPressHandler); + this.setBackKeyPressHandler(keyPressHandler); + await this.executeStackDestinationPrompt(params); } else { - const orgMsg = 'Choose an organization where you want to create a stack: '; - const destinationOrg = await cloneCommand.execute(new HandleOrgCommand({ msg: orgMsg }, this)); - const orgUid = orgUidList[destinationOrg.Organization]; - await cloneCommand.execute(new CreateNewStackCommand({ orgUid, stackAbortController }, this)); + await this.executeBranchDestinationPrompt(params); } - await cloneCommand.execute(new CloneTypeSelectionCommand(null, this)); + return resolve(); } catch (error) { - console.log(error); - stackAbortController.signal.aborted = true; reject(error); - } finally { - // If not aborted and ran successfully - if (!stackAbortController.signal.aborted) { - // Call clean dir. - rimraf(this.pathDir, function () { - // eslint-disable-next-line no-console - console.log('Stack cloning process have been completed successfully'); - }); - } } }); } + async executeStackDestinationPrompt(params) { + try { + this.setExectingCommand(1); + const { org, canCreateStack } = params; + if (!canCreateStack.stackCreate) { + const stackMsg = 'Choose the destination stack:'; + await cloneCommand.execute(new HandleDestinationStackCommand({ org, msg: stackMsg, isSource: false }, this)); + this.executeBranchDestinationPrompt(params); + } else { + const orgUid = orgUidList[org.Organization]; + await cloneCommand.execute(new CreateNewStackCommand({ orgUid }, this)); + this.removeBackKeyPressHandler(); + await cloneCommand.execute(new CloneTypeSelectionCommand(null, this)); + } + } catch (error) { + throw error; + } + } + + async executeBranchDestinationPrompt(parentParams) { + try { + this.setExectingCommand(2); + await cloneCommand.execute(new HandleBranchCommand({ isSource: false, api_key: config.target_stack }, this, this.executeStackDestinationPrompt.bind(this, parentParams))); + this.removeBackKeyPressHandler(); + await cloneCommand.execute(new CloneTypeSelectionCommand(null, this)); + } catch (error) { + throw error; + } + } + + setCreateNewStackPrompt(createNewStackPrompt) { + this.createNewStackPrompt = createNewStackPrompt; + } + async setBranch() { if (!config.sourceStackBranch) { try { @@ -453,38 +489,21 @@ class CloneHandler { } async createNewStack(options) { - let keyPressHandler; return new Promise(async (resolve, reject) => { try { - const { orgUid, stackAbortController } = options; + const { orgUid } = options; + this.displayBackOptionMessage(); let inputvalue; - let uiPromise; - - keyPressHandler = async function (_ch, key) { - if (key.name === 'left' && key.shift) { - stackAbortController.abort(); - // We need to close the inquirer promise correctly, otherwise the unclosed question/answer text is displayed in next line. - if (uiPromise) { - uiPromise.ui.close(); - } - console.clear(); - process.stdin.removeListener('keypress', keyPressHandler); - await cloneCommand.undo(); - } - }; - process.stdin.addListener('keypress', keyPressHandler); - - const ui = new inquirer.ui.BottomBar(); - ui.updateBottomBar(chalk.cyan('\nPress shift & left arrow together to undo the operation\n')); - if (!config.stackName) { - uiPromise = inquirer.prompt(stackName); - inputvalue = await uiPromise; + prompt.start(); + prompt.message = ''; + this.setCreateNewStackPrompt(prompt); + inputvalue = await this.getNewStackPromptResult(); + this.setCreateNewStackPrompt(null); } else { inputvalue = { stack: config.stackName }; } - - if (stackAbortController.signal.aborted) { + if (this.executingCommand === 0 || !inputvalue) { return reject(); } @@ -504,15 +523,28 @@ class CloneHandler { }); } catch (error) { return reject(error); - } finally { - if (keyPressHandler) { - process.stdin.removeListener('keypress', keyPressHandler); - } } }); } + getNewStackPromptResult() { + return new Promise((resolve) => { + prompt.get({ properties: { name: { description: colors.white(stackName.message), default: colors.grey(stackName.default), } } }, + function (_, result) { + if (prompt.stopped) { + prompt.stopped = false; + resolve(); + } else { + let _name = result.name.replace(/\[\d+m/g, ''); + _name = _name.replace(//g, ''); + resolve({ stack: _name }); + } + }); + }); + } + async cloneTypeSelection() { + console.clear(); return new Promise(async (resolve, reject) => { const choices = [ 'Structure (all modules except entries & assets)', diff --git a/packages/contentstack-command/package.json b/packages/contentstack-command/package.json index 1f1507affc..3c19d1fbf0 100644 --- a/packages/contentstack-command/package.json +++ b/packages/contentstack-command/package.json @@ -1,7 +1,7 @@ { "name": "@contentstack/cli-command", "description": "Contentstack CLI plugin for configuration", - "version": "1.2.8", + "version": "1.2.9", "author": "Contentstack", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -17,7 +17,7 @@ "format": "eslint src/**/*.ts --fix" }, "dependencies": { - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-utilities": "^1.4.5", "contentstack": "^3.10.1" }, "devDependencies": { diff --git a/packages/contentstack-config/README.md b/packages/contentstack-config/README.md index f86dce7021..6d021e8b16 100644 --- a/packages/contentstack-config/README.md +++ b/packages/contentstack-config/README.md @@ -18,7 +18,7 @@ $ npm install -g @contentstack/cli-config $ csdx COMMAND running command... $ csdx (--version) -@contentstack/cli-config/1.4.6 darwin-x64 node-v18.16.0 +@contentstack/cli-config/1.4.7 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-config/package.json b/packages/contentstack-config/package.json index dcbba6188c..e32edaaec1 100644 --- a/packages/contentstack-config/package.json +++ b/packages/contentstack-config/package.json @@ -1,7 +1,7 @@ { "name": "@contentstack/cli-config", "description": "Contentstack CLI plugin for configuration", - "version": "1.4.6", + "version": "1.4.7", "author": "Contentstack", "scripts": { "build": "npm run clean && npm run compile", @@ -21,8 +21,8 @@ "test:unit:report": "nyc --extension .ts mocha --forbid-only \"test/unit/**/*.test.ts\"" }, "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "chalk": "^4.0.0", "debug": "^4.1.1", "inquirer": "8.2.4", diff --git a/packages/contentstack-export-to-csv/.gitignore b/packages/contentstack-export-to-csv/.gitignore index a46b12259a..5e74e314c4 100644 --- a/packages/contentstack-export-to-csv/.gitignore +++ b/packages/contentstack-export-to-csv/.gitignore @@ -6,3 +6,5 @@ /yarn.lock coverage node_modules +data +logs diff --git a/packages/contentstack-export-to-csv/package.json b/packages/contentstack-export-to-csv/package.json index 58f43fcede..203dcc94da 100644 --- a/packages/contentstack-export-to-csv/package.json +++ b/packages/contentstack-export-to-csv/package.json @@ -1,12 +1,12 @@ { "name": "@contentstack/cli-cm-export-to-csv", "description": "Export entities to csv", - "version": "1.3.8", + "version": "1.3.9", "author": "Abhinav Gupta @abhinav-from-contentstack", "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "chalk": "^4.1.0", "fast-csv": "^4.3.6", "inquirer": "8.2.4", diff --git a/packages/contentstack-export-to-csv/src/commands/cm/export-to-csv.js b/packages/contentstack-export-to-csv/src/commands/cm/export-to-csv.js index 17d281b07c..4716b42ba7 100644 --- a/packages/contentstack-export-to-csv/src/commands/cm/export-to-csv.js +++ b/packages/contentstack-export-to-csv/src/commands/cm/export-to-csv.js @@ -1,5 +1,12 @@ const { Command } = require('@contentstack/cli-command'); -const { configHandler, managementSDKClient, flags, isAuthenticated } = require('@contentstack/cli-utilities'); +const { + configHandler, + managementSDKClient, + flags, + isAuthenticated, + cliux, + doesBranchExist, +} = require('@contentstack/cli-utilities'); const util = require('../../util'); const config = require('../../util/config'); @@ -41,6 +48,11 @@ class ExportToCsvCommand extends Command { required: false, multiple: false, }), + branch: flags.string({ + description: 'Branch from which entries need to be exported', + multiple: false, + required: false, + }), }; async run() { @@ -55,6 +67,7 @@ class ExportToCsvCommand extends Command { locale: locale, 'content-type': contentTypesFlag, alias: managementTokenAlias, + branch: branchUid, }, } = await this.parse(ExportToCsvCommand); @@ -76,6 +89,7 @@ class ExportToCsvCommand extends Command { let stackAPIClient; let language; let contentTypes = []; + let stackBranches; const listOfTokens = configHandler.get('tokens'); if (managementTokenAlias && listOfTokens[managementTokenAlias]) { @@ -110,7 +124,34 @@ class ExportToCsvCommand extends Command { } stackAPIClient = this.getStackClient(managementAPIClient, stack); + + if (branchUid) { + try { + const branchExists = await doesBranchExist(stackAPIClient, branchUid); + if (branchExists?.errorCode) { + throw new Error(branchExists.errorMessage); + } + stack.branch_uid = branchUid; + stackAPIClient = this.getStackClient(managementAPIClient, stack); + } catch (error) { + if (error.message || error.errorMessage) { + cliux.error(util.formatError(error)); + this.exit(); + } + } + } else { + stackBranches = await this.getStackBranches(stackAPIClient); + if (stackBranches === undefined) { + stackAPIClient = this.getStackClient(managementAPIClient, stack); + } else { + const { branch } = await util.chooseBranch(stackBranches); + stack.branch_uid = branch; + stackAPIClient = this.getStackClient(managementAPIClient, stack); + } + } + const contentTypeCount = await util.getContentTypeCount(stackAPIClient); + const environments = await util.getEnvironments(stackAPIClient); // fetch environments, because in publish details only env uid are available and we need env names if (contentTypesFlag) { @@ -189,7 +230,7 @@ class ExportToCsvCommand extends Command { util.write(this, listOfUsers, fileName, 'organization details'); } catch (error) { - if (error.message) { + if (error.message || error.errorMessage) { this.log(util.formatError(error)); } } @@ -197,7 +238,7 @@ class ExportToCsvCommand extends Command { } } } catch (error) { - if (error.message) { + if (error.message || error.errorMessage) { this.log(util.formatError(error)); } } @@ -208,13 +249,26 @@ class ExportToCsvCommand extends Command { } getStackClient(managementAPIClient, stack) { + const stackInit = { + api_key: stack.apiKey, + branch_uid: stack.branch_uid, + }; if (stack.token) { return managementAPIClient.stack({ - api_key: stack.apiKey, + ...stackInit, management_token: stack.token, }); } - return managementAPIClient.stack({ api_key: stack.apiKey }); + return managementAPIClient.stack(stackInit); + } + + getStackBranches(stackAPIClient) { + return stackAPIClient + .branch() + .query() + .find() + .then(({ items }) => (items !== undefined ? items : [])) + .catch((_err) => {}); } } @@ -226,8 +280,8 @@ ExportToCsvCommand.examples = [ 'Exporting entries to csv', 'csdx cm:export-to-csv --action --locale --alias --content-type ', '', - 'Exporting entries to csv with stack name provided', - 'csdx cm:export-to-csv --action --locale --alias --content-type --stack-name ', + 'Exporting entries to csv with stack name provided and branch name provided', + 'csdx cm:export-to-csv --action --locale --alias --content-type --stack-name --branch ', '', 'Exporting organization users to csv', 'csdx cm:export-to-csv --action --org ', diff --git a/packages/contentstack-export-to-csv/src/util/index.js b/packages/contentstack-export-to-csv/src/util/index.js index 4c162ba036..3106d45fe0 100644 --- a/packages/contentstack-export-to-csv/src/util/index.js +++ b/packages/contentstack-export-to-csv/src/util/index.js @@ -8,6 +8,7 @@ const debug = require('debug')('export-to-csv'); const checkboxPlus = require('inquirer-checkbox-plus-prompt'); const config = require('./config.js'); +const { cliux } = require('@contentstack/cli-utilities'); const directory = './data'; const delimeter = os.platform() === 'win32' ? '\\' : '/'; @@ -126,6 +127,26 @@ function chooseStack(managementAPIClient, orgUid) { }); } +async function chooseBranch(branchList) { + try { + const branches = await branchList; + + const branchesArray = branches.map((branch) => branch.uid); + + let _chooseBranch = [ + { + type: 'list', + name: 'branch', + message: 'Choose a Branch', + choices: branchesArray, + }, + ]; + return await inquirer.prompt(_chooseBranch); + } catch (err) { + cliux.error(err); + } +} + function getStacks(managementAPIClient, orgUid) { return new Promise((resolve, reject) => { let result = {}; @@ -167,7 +188,7 @@ function chooseContentType(stackAPIClient, skip) { } function chooseInMemContentTypes(contentTypesList) { - return new Promise(async (resolve, reject) => { + return new Promise((resolve, reject) => { let _chooseContentType = [ { type: 'checkbox-plus', @@ -213,7 +234,7 @@ function getContentTypes(stackAPIClient, skip) { let result = {}; stackAPIClient .contentType() - .query({ skip: skip * 100 }) + .query({ skip: skip * 100, include_branch: true }) .find() .then((contentTypes) => { contentTypes.items.forEach((contentType) => { @@ -400,7 +421,7 @@ function startupQuestions() { }); } -function getOrgUsers(managementAPIClient, orgUid, ecsv) { +function getOrgUsers(managementAPIClient, orgUid) { return new Promise((resolve, reject) => { managementAPIClient .getUser({ include_orgs_roles: true }) @@ -442,10 +463,7 @@ async function getUsers(managementAPIClient, organization, params, result = []) await wait(200); return getUsers(managementAPIClient, organization, params, result); } - } catch (error) { - console.error(error); - throw error; - } + } catch (error) {} } function getMappedUsers(users) { @@ -612,6 +630,7 @@ function wait(time) { module.exports = { chooseOrganization: chooseOrganization, chooseStack: chooseStack, + chooseBranch: chooseBranch, chooseContentType: chooseContentType, chooseLanguage: chooseLanguage, getEntries: getEntries, diff --git a/packages/contentstack-export/README.md b/packages/contentstack-export/README.md index 15a38250dc..6babb9b5bb 100755 --- a/packages/contentstack-export/README.md +++ b/packages/contentstack-export/README.md @@ -48,7 +48,7 @@ $ npm install -g @contentstack/cli-cm-export $ csdx COMMAND running command... $ csdx (--version) -@contentstack/cli-cm-export/1.5.8 darwin-x64 node-v18.16.0 +@contentstack/cli-cm-export/1.5.9 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND @@ -146,5 +146,9 @@ EXAMPLES $ csdx cm:stacks:export --branch [optional] branch name ``` +_Mangement token and config file: [example_config/management_config.json](https://github.com/contentstack/cli/blob/main/packages/contentstack-export/example_config/management_config.json)_ + +_Auth token and config file: [example_config/auth_config.json](https://github.com/contentstack/cli/blob/main/packages/contentstack-export/example_config/auth_config.json)_ + _See code: [src/commands/cm/stacks/export.js](https://github.com/contentstack/cli/blob/main/packages/contentstack-export/src/commands/cm/stacks/export.js)_ diff --git a/packages/contentstack-export/example_config/auth_config.json b/packages/contentstack-export/example_config/auth_config.json new file mode 100644 index 0000000000..bfc4679440 --- /dev/null +++ b/packages/contentstack-export/example_config/auth_config.json @@ -0,0 +1,13 @@ +{ + "master_locale": { + "name": "English - United States", + "code": "en-us" + }, + "source_stack": "bltXXXXXXXXXX", + "data": "file path", + "branchName":"example1", + "moduleName": "content-types", + "fetchConcurrency": 5, + "writeConcurrency": 5, + "securedAssets":false +} diff --git a/packages/contentstack-export/example_config/management_config.json b/packages/contentstack-export/example_config/management_config.json new file mode 100644 index 0000000000..8d5ff4ea3b --- /dev/null +++ b/packages/contentstack-export/example_config/management_config.json @@ -0,0 +1,12 @@ +{ + "master_locale": { + "name": "English - United States", + "code": "en-us" + }, + "data": "file path", + "branchName":"example1", + "moduleName": "content-types", + "fetchConcurrency": 5, + "writeConcurrency": 5, + "securedAssets":false +} diff --git a/packages/contentstack-export/package.json b/packages/contentstack-export/package.json index c6696d8156..2f20b7e4ad 100644 --- a/packages/contentstack-export/package.json +++ b/packages/contentstack-export/package.json @@ -1,12 +1,12 @@ { "name": "@contentstack/cli-cm-export", "description": "Contentstack CLI plugin to export content from stack", - "version": "1.5.8", + "version": "1.5.9", "author": "Contentstack", "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/command": "^1.8.16", "@oclif/config": "^1.18.3", "async": "^3.2.4", diff --git a/packages/contentstack-export/src/app.js b/packages/contentstack-export/src/app.js index 768ae99f2e..25bc410042 100755 --- a/packages/contentstack-export/src/app.js +++ b/packages/contentstack-export/src/app.js @@ -36,7 +36,7 @@ exports.initial = async (config) => { await allExport(APIClient, stackAPIClient, config, types, branch.uid); } } catch (error) { - addlogs(config, `failed export contents ${branch.uid} ${util.formatError(error)}`, 'error'); + addlogs(config, `failed export contents '${branch.uid}' ${util.formatError(error)}`, 'error'); } } } else { @@ -47,7 +47,7 @@ exports.initial = async (config) => { await allExport(APIClient, stackAPIClient, config, types); } } catch (error) { - addlogs(config, `failed export contents ${util.formatError(error)}`, 'error'); + addlogs(config, `failed export contents. ${util.formatError(error)}`, 'error'); } } }; @@ -77,9 +77,8 @@ exports.initial = async (config) => { resolve(); }) .catch((error) => { - console.log('error', error && error.message); if (error && error.errors && error.errors.api_key) { - addlogs(config, chalk.red('Stack Api key ' + error.errors.api_key[0], 'Please enter valid Key', 'error')); + addlogs(config, `Stack Api key '${error.errors.api_key[0]}', Please enter valid Key`, 'error'); addlogs(config, 'The log for this is stored at ' + config.data + '/export/logs', 'success'); } else { addlogs(config, `${util.formatError(error)}`, 'error'); @@ -112,7 +111,7 @@ const singleExport = async (APIClient, stackAPIClient, moduleName, types, config config = _.merge(config, master_locale); } } - addlogs(config, moduleName + ' was exported successfully!', 'success'); + addlogs(config, `Module '${moduleName}' was exported successfully!`, 'success'); addlogs(config, 'The log for this is stored at ' + path.join(config.data, 'logs', 'export'), 'success'); } else { addlogs(config, 'Please provide valid module name.', 'error'); @@ -120,8 +119,8 @@ const singleExport = async (APIClient, stackAPIClient, moduleName, types, config return true; } catch (error) { addlogs(config, `${util.formatError(error)}`, 'error'); - addlogs(config, 'Failed to migrate ' + moduleName, 'error'); - addlogs(config, 'The log for this is stored at ' + path.join(config.data, 'logs', 'export'), 'error'); + addlogs(config, `Failed to migrate module '${moduleName}'`, 'error'); + addlogs(config, `The log for this is stored at '${path.join(config.data, 'logs', 'export')}'`, 'error'); } }; @@ -149,13 +148,9 @@ const allExport = async (APIClient, stackAPIClient, config, types, branchName) = addlogs(config, util.formatError(error), 'error'); addlogs( config, - chalk.red( - 'Failed to migrate stack: ' + - (config.sourceStackName || config.source_stack) + - '. Please check error logs for more info', - ), + `Failed to migrate stack '${config.sourceStackName || config.source_stack}'. Please check error logs for more info.`, 'error', ); - addlogs(config, 'The log for this is stored at ' + path.join(config.data, 'logs', 'export'), 'error'); + addlogs(config, `The log for this is stored at '${path.join(config.data, 'logs', 'export')}'`, 'error'); } }; diff --git a/packages/contentstack-export/src/commands/cm/stacks/export.js b/packages/contentstack-export/src/commands/cm/stacks/export.js index 619bd17da8..a9882a32f9 100644 --- a/packages/contentstack-export/src/commands/cm/stacks/export.js +++ b/packages/contentstack-export/src/commands/cm/stacks/export.js @@ -1,6 +1,6 @@ /* eslint-disable complexity */ const { Command } = require('@contentstack/cli-command'); -const { printFlagDeprecation, configHandler, flags, isAuthenticated } = require('@contentstack/cli-utilities'); +const { printFlagDeprecation, configHandler, flags, isAuthenticated, cliux } = require('@contentstack/cli-utilities'); const { configWithMToken, parameterWithMToken, @@ -71,10 +71,10 @@ class ExportCommand extends Command { exportCommandFlags, ); } else { - this.log('Please provide a valid command. Run "csdx cm:export --help" command to view the command usage'); + cliux.print(`error: Please provide a valid command. Run "csdx cm:export --help" command to view the command usage`, {color: 'red'}); } } else { - this.log(alias + ' management token is not present, please add managment token first'); + cliux.print(`error: ${alias} management token is not present, please add managment token first`, {color: 'red'}); } } else if (isAuthenticated()) { if (extConfig) { @@ -108,10 +108,10 @@ class ExportCommand extends Command { exportCommandFlags, ); } else { - this.log('Please provide a valid command. Run "csdx cm:export --help" command to view the command usage'); + cliux.print(`error: Please provide a valid command. Run "csdx cm:export --help" command to view the command usage`, {color: 'red'}); } } else { - this.log('Login or provide the alias for management token'); + cliux.print(`error: Login or provide the alias for management token`, {color: 'red'}); } } } diff --git a/packages/contentstack-export/src/lib/export/assets.js b/packages/contentstack-export/src/lib/export/assets.js index c944fa3dac..9f06dd77d3 100644 --- a/packages/contentstack-export/src/lib/export/assets.js +++ b/packages/contentstack-export/src/lib/export/assets.js @@ -17,6 +17,7 @@ const helper = require('../util/helper'); const { addlogs } = require('../util/log'); let config = require('../../config/default'); +const { formatError } = require('../util'); module.exports = class ExportAssets { config; @@ -86,7 +87,8 @@ module.exports = class ExportAssets { .catch((error) => { addlogs( self.config, - chalk.red('The following asset failed to download\n' + JSON.stringify(assetJSON)), + `Asset '${assetJSON.uid}' failed to download.\n ${formatError(error)}`, + 'error' ); addlogs(self.config, error, 'error'); }); @@ -98,8 +100,8 @@ module.exports = class ExportAssets { }) .catch((err) => { addlogs( - { errorCode: err && err.code, uid: assetJSON.uid }, - `Asset download failed - ${assetJSON.uid}`, + self.config, + `Asset '${assetJSON.uid}' download failed. ${formatError(err)}`, 'error', ); return err; @@ -113,8 +115,8 @@ module.exports = class ExportAssets { // helper.writeFileSync(this.assetContentsFile, self.assetContents) }) .catch((error) => { - console.log('Error fetch/download the asset', error && error.message); - addlogs(self.config, 'Asset batch ' + (batch + 1) + ' failed to download', 'error'); + addlogs(self.config, `Asset batch ${batch + 1} failed to download`, 'error'); + addlogs(self.config, formatError(error), 'error'); addlogs(self.config, error, 'error'); }); }) @@ -135,7 +137,7 @@ module.exports = class ExportAssets { return resolve(); }) .catch((error) => { - addlogs(self.config, error, 'success'); + addlogs(self.config, error, 'error'); reject(error); }); }) @@ -143,14 +145,15 @@ module.exports = class ExportAssets { helper.writeFileSync(self.assetContentsFile, self.assetContents); addlogs( self.config, - chalk.red('Asset export failed due to the following errors ' + JSON.stringify(error), 'error'), + `Asset export failed. ${formatError(error)}`, + 'error' ); - addlogs(self.config, error, 'success'); + addlogs(self.config, error, 'error'); reject(error); }); }) .catch((error) => { - addlogs(self.config, error, 'success'); + addlogs(self.config, error, 'error'); reject(error); }); }); @@ -175,7 +178,7 @@ module.exports = class ExportAssets { return resolve(); }) .catch((error) => { - addlogs(self.config, chalk.red('Error while exporting asset-folders!'), 'error'); + addlogs(self.config, `Error while exporting asset-folders!\n ${formatError(error)}`, 'error'); return reject(error); }); }) @@ -319,7 +322,6 @@ module.exports = class ExportAssets { }) .catch((error) => { addlogs(self.config, error, 'error'); - console.log('Error on fetch', error && error.message); if (error.status === 408) { console.log('retrying', uid); @@ -383,6 +385,7 @@ module.exports = class ExportAssets { return resolve(); }) .on('error', (error) => { + addlogs(self.config, `Download ${asset.filename}: ${asset.uid} failed!`, 'error'); addlogs(self.config, error, 'error'); reject(error); }); diff --git a/packages/contentstack-export/src/lib/export/content-types.js b/packages/contentstack-export/src/lib/export/content-types.js index 3bb2c11494..fd0e0947b9 100644 --- a/packages/contentstack-export/src/lib/export/content-types.js +++ b/packages/contentstack-export/src/lib/export/content-types.js @@ -37,7 +37,7 @@ class ContentTypesExport { await this.writeContentTypes(this.contentTypes); addlogs(this.exportConfig, chalk.green('Content type(s) exported successfully'), 'success'); } catch (error) { - addlogs(this.exportConfig, chalk.red(`Failed to export content types ${formatError(error)}`), 'error'); + addlogs(this.exportConfig, `Failed to export content types ${formatError(error)}`, 'error'); throw new Error('Failed to export content types'); } } @@ -58,7 +58,7 @@ class ContentTypesExport { } return await this.getContentTypes(skip); } else { - console.log('No content types returned for the given query'); + addlogs(this.exportConfig, 'No content types returned for the given query', 'info'); } } diff --git a/packages/contentstack-export/src/lib/export/custom-roles.js b/packages/contentstack-export/src/lib/export/custom-roles.js index 2a8195f866..cd786f274f 100644 --- a/packages/contentstack-export/src/lib/export/custom-roles.js +++ b/packages/contentstack-export/src/lib/export/custom-roles.js @@ -45,7 +45,7 @@ module.exports = class ExportCustomRoles { ); self.customRoles = {}; customRoles.forEach((role) => { - addlogs(self.config, role.name + ' role was exported successfully', 'success'); + addlogs(self.config, `'${role.name}' role was exported successfully`, 'success'); self.customRoles[role.uid] = role; }); helper.writeFileSync(path.join(rolesFolderPath, self.rolesConfig.fileName), self.customRoles); @@ -54,13 +54,12 @@ module.exports = class ExportCustomRoles { if (error.statusCode === 401) { addlogs( self.config, - chalk.red('You are not allowed to export roles, Unless you provide email and password in config'), + 'You are not allowed to export roles, Unless you provide email and password in config', 'error', ); return; } - addlogs(self.config, 'Error occurred in exporting roles. ' + error && error.message, 'error'); - addlogs(self.config, formatError(error), 'error'); + addlogs(self.config, `Error occurred in exporting roles. ${formatError(error)}`, 'error'); throw error; } } diff --git a/packages/contentstack-export/src/lib/export/entries.js b/packages/contentstack-export/src/lib/export/entries.js index 499e16a0db..3091436cb7 100644 --- a/packages/contentstack-export/src/lib/export/entries.js +++ b/packages/contentstack-export/src/lib/export/entries.js @@ -32,7 +32,7 @@ class EntriesExport { const locales = await fileHelper.readFile(this.localesFilePath); const contentTypes = await fileHelper.readFile(this.schemaFilePath); if (contentTypes.length === 0) { - addlogs(this.exportConfig, 'No content types found to export entries'); + addlogs(this.exportConfig, 'No content types found to export entries', 'info'); return; } const entryRequestOptions = this.createRequestObjects(locales, contentTypes); @@ -52,13 +52,13 @@ class EntriesExport { await fileHelper.writeLargeFile(entriesFilePath, entries); addlogs( this.exportConfig, - `Exported entries of type ${requestOption.content_type} locale ${requestOption.locale}`, + `Exported entries of type '${requestOption.content_type}' locale '${requestOption.locale}'`, 'success', ); if (this.exportConfig.versioning) { addlogs( this.exportConfig, - `Started export versioned entries of type ${requestOption.content_type} locale ${requestOption.locale}`, + `Started export versioned entries of type '${requestOption.content_type}' locale '${requestOption.locale}'`, 'info', ); for (let entry of entries) { @@ -85,7 +85,7 @@ class EntriesExport { await executeTask(versionedEntries, write.bind(this), { concurrency: this.writeConcurrency }); addlogs( this.exportConfig, - `Exported versioned entries of type ${requestOption.content_type} locale ${requestOption.locale}`, + `Exported versioned entries of type '${requestOption.content_type}' locale '${requestOption.locale}'`, 'success', ); } @@ -94,7 +94,7 @@ class EntriesExport { } addlogs(this.exportConfig, chalk.green('Entries exported successfully'), 'success'); } catch (error) { - addlogs(this.exportConfig, chalk.red(`Failed to export entries ${formatError(error)}`), 'error'); + addlogs(this.exportConfig, `Failed to export entries ${formatError(error)}`, 'error'); throw new Error('Failed to export entries'); } } diff --git a/packages/contentstack-export/src/lib/export/environments.js b/packages/contentstack-export/src/lib/export/environments.js index 179adbdf01..52255cf0f1 100644 --- a/packages/contentstack-export/src/lib/export/environments.js +++ b/packages/contentstack-export/src/lib/export/environments.js @@ -66,7 +66,7 @@ module.exports = class ExportEnvironments { } }) .catch((error) => { - addlogs(self.config, `Environments export failed ${formatError(error)}`, 'error'); + addlogs(self.config, `Environments export failed. ${formatError(error)}`, 'error'); reject(error); }); }); diff --git a/packages/contentstack-export/src/lib/export/extensions.js b/packages/contentstack-export/src/lib/export/extensions.js index 8462e71150..e96df98c56 100644 --- a/packages/contentstack-export/src/lib/export/extensions.js +++ b/packages/contentstack-export/src/lib/export/extensions.js @@ -61,7 +61,7 @@ module.exports = class ExportExtensions { resolve(); }) .catch((error) => { - addlogs(self.config, `Failed to export extensions ${formatError(error)}`, 'error'); + addlogs(self.config, `Failed to export extensions. ${formatError(error)}`, 'error'); reject(); }); }); diff --git a/packages/contentstack-export/src/lib/export/global-fields.js b/packages/contentstack-export/src/lib/export/global-fields.js index 7f7a3d5006..b2f4dae4e4 100644 --- a/packages/contentstack-export/src/lib/export/global-fields.js +++ b/packages/contentstack-export/src/lib/export/global-fields.js @@ -95,7 +95,7 @@ module.exports = class ExportGlobalFields { } return self.getGlobalFields(skip, globalFieldConfig).then(resolve).catch(reject); } catch (error) { - addlogs(globalFieldConfig, chalk.red(`Failed to export global-fields ${formatError(error)}`), 'error'); + addlogs(globalFieldConfig, `Failed to export global-fields. ${formatError(error)}`, 'error'); reject(error); } }) diff --git a/packages/contentstack-export/src/lib/export/labels.js b/packages/contentstack-export/src/lib/export/labels.js index 30ed6f1703..19a5142bfd 100644 --- a/packages/contentstack-export/src/lib/export/labels.js +++ b/packages/contentstack-export/src/lib/export/labels.js @@ -37,7 +37,7 @@ module.exports = class ExportLabels { .then((response) => { if (response.items.length !== 0) { response.items.forEach(function (label) { - addlogs(self.config, label.name + ' labels was exported successfully', 'success'); + addlogs(self.config, `'${label.name}' label was exported successfully`, 'success'); self.labels[label.uid] = label; const deleteItems = self.config.modules.labels.invalidKeys; deleteItems.forEach((e) => delete label[e]); @@ -53,15 +53,13 @@ module.exports = class ExportLabels { if (error.statusCode === 401) { addlogs( self.config, - chalk.red( - 'You are not allowed to export label, Unless you provide email and password in config', - 'error', - ), + 'You are not allowed to export label, Unless you provide email and password in config', + 'error' ); return resolve(); } - addlogs(self.config, formatError(error), 'error'); + addlogs(self.config, `Failed to export labels. ${formatError(error)}`, 'error'); reject(); }); }); diff --git a/packages/contentstack-export/src/lib/export/locales.js b/packages/contentstack-export/src/lib/export/locales.js index 09fa74b034..0d7ec8fe23 100644 --- a/packages/contentstack-export/src/lib/export/locales.js +++ b/packages/contentstack-export/src/lib/export/locales.js @@ -33,7 +33,7 @@ class LocaleExport { await fileHelper.writeFile(path.join(this.localesPath, this.masterLocaleConfig.fileName), this.masterLocale); addlogs(this.exportConfig, 'Completed locale export', 'success'); } catch (error) { - addlogs(this.exportConfig, chalk.red(`Failed to export locales ${formatError(error)}`), 'error'); + addlogs(this.exportConfig, `Failed to export locales. ${formatError(error)}`, 'error'); throw new Error('Failed to export locales'); } } diff --git a/packages/contentstack-export/src/lib/export/marketplace-apps.js b/packages/contentstack-export/src/lib/export/marketplace-apps.js index 4ded7a98f6..0165bfe0a7 100644 --- a/packages/contentstack-export/src/lib/export/marketplace-apps.js +++ b/packages/contentstack-export/src/lib/export/marketplace-apps.js @@ -107,11 +107,12 @@ module.exports = class ExportMarketplaceApps { } async exportInstalledExtensions() { + const client = await managementSDKClient({ host: this.developerHubBaseUrl.split("://").pop() }) const installedApps = (await this.getAllStackSpecificApps()) || []; if (!_.isEmpty(installedApps)) { for (const [index, app] of _.entries(installedApps)) { - await this.getAppConfigurations(installedApps, [+index, app]); + await this.getAppConfigurations(client, installedApps, [+index, app]); } await writeFileSync(path.join(this.marketplaceAppPath, this.marketplaceAppConfig.fileName), installedApps); @@ -149,36 +150,38 @@ module.exports = class ExportMarketplaceApps { return listOfApps; }) .catch((error) => { - log(this.config, `Failed to export marketplace-apps ${formatError(error)}`, 'error'); + log(this.config, `Failed to export marketplace-apps. ${formatError(error)}`, 'error'); }); } - getAppConfigurations(installedApps, [index, app]) { - const appName = app.manifest.name; + async getAppConfigurations(sdkClient, installedApps, [index, appInstallation]) { + const appName = appInstallation.manifest.name; log(this.config, `Exporting ${appName} app and it's config.`, 'success'); - return this.httpClient - .get(`${this.developerHubBaseUrl}/installations/${app.uid}/installationData`) - .then(async ({ data: result }) => { - const { data, error } = result; - - if (_.has(data, 'server_configuration')) { - if (!this.nodeCrypto && _.has(data, 'server_configuration')) { - await this.createNodeCryptoInstance(); - } - - if (!_.isEmpty(data.server_configuration)) { - installedApps[index]['server_configuration'] = this.nodeCrypto.encrypt(data.server_configuration); - log(this.config, `Exported ${appName} app and it's config.`, 'success'); - } else { - log(this.config, `Exported ${appName} app`, 'success'); - } - } else if (error) { - log(this.config, `Error on exporting ${appName} app and it's config.`, 'error'); + await sdkClient + .organization(this.config.org_uid) + .app(appInstallation.manifest.uid) + .installation(appInstallation.uid) + .installationData() + .then(async result => { + const {data, error} = result; + if (_.has(data, 'server_configuration')) { + if (!this.nodeCrypto && _.has(data, 'server_configuration')) { + await this.createNodeCryptoInstance(); } - }) - .catch((err) => { - log(this.config, `Failed to export ${appName} app config ${formatError(err)}`, 'error'); - }); + + if (!_.isEmpty(data.server_configuration)) { + installedApps[index]['server_configuration'] = this.nodeCrypto.encrypt(data.server_configuration); + log(this.config, `Exported ${appName} app and it's config.`, 'success'); + } else { + log(this.config, `Exported ${appName} app`, 'success'); + } + } else if (error) { + log(this.config, `Error on exporting ${appName} app and it's config.`, 'error'); + } + }) + .catch(err => { + log(this.config, `Failed to export ${appName} app config ${formatError(err)}`, 'error'); + }) } }; diff --git a/packages/contentstack-export/src/lib/export/stack.js b/packages/contentstack-export/src/lib/export/stack.js index 63a5d0830d..db70375153 100644 --- a/packages/contentstack-export/src/lib/export/stack.js +++ b/packages/contentstack-export/src/lib/export/stack.js @@ -33,7 +33,6 @@ module.exports = class ExportStack { .stack({ api_key: self.config.source_stack }) .fetch() .catch((error) => { - console.log(error); }); if (tempStackData && tempStackData.org_uid) { diff --git a/packages/contentstack-export/src/lib/export/webhooks.js b/packages/contentstack-export/src/lib/export/webhooks.js index 4ab187dee5..6c053d97b6 100644 --- a/packages/contentstack-export/src/lib/export/webhooks.js +++ b/packages/contentstack-export/src/lib/export/webhooks.js @@ -63,13 +63,13 @@ module.exports = class ExportWebhooks { if (error.statusCode === 401) { addlogs( self.config, - chalk.red('You are not allowed to export webhooks, Unless you provide email and password in config'), + 'You are not allowed to export webhooks, Unless you provide email and password in config', 'error', ); return resolve(); } - addlogs(self.config, formatError(error), 'error'); - reject('Failed export webhooks'); + addlogs(self.config, `Failed to export webhooks. ${formatError(error)}`, 'error'); + reject('Failed to export webhooks'); }); }); } diff --git a/packages/contentstack-export/src/lib/export/workflows.js b/packages/contentstack-export/src/lib/export/workflows.js index a00eacd570..4ae13d3137 100644 --- a/packages/contentstack-export/src/lib/export/workflows.js +++ b/packages/contentstack-export/src/lib/export/workflows.js @@ -59,10 +59,8 @@ module.exports = class ExportWorkFlows { if (error.statusCode === 401) { addlogs( self.config, - chalk.red( - 'You are not allowed to export workflow, Unless you provide email and password in config', - 'error', - ), + 'You are not allowed to export workflow, Unless you provide email and password in config', + 'error', ); return resolve(); } @@ -86,8 +84,7 @@ module.exports = class ExportWorkFlows { } } } catch (error) { - console.log('Error getting roles', error && error.message); - addlogs(self.config, 'Error fetching roles in export workflows task.', 'error'); + addlogs(self.config, `Error fetching roles in export workflows task. ${formatError(error)}`, 'error'); throw new Error({ message: 'Error fetching roles in export workflows task.' }); } } @@ -102,8 +99,7 @@ module.exports = class ExportWorkFlows { deleteItems.forEach((e) => delete workflow[e]); } } catch (error) { - console.log('Error getting workflow data', error && error.message); - addlogs(self.config, 'Error fetching workflow data in export workflows task.', 'error'); + addlogs(self.config, `Error fetching workflow data in export workflows task. ${formatError(error)}`, 'error'); throw error; } } diff --git a/packages/contentstack-export/src/lib/util/log.js b/packages/contentstack-export/src/lib/util/log.js index 6ca8ed503b..d61ab39026 100755 --- a/packages/contentstack-export/src/lib/util/log.js +++ b/packages/contentstack-export/src/lib/util/log.js @@ -89,7 +89,10 @@ function init(_logPath) { errorLogger = winston.createLogger({ transports: [ new winston.transports.File(errorTransport), - new winston.transports.Console({ level: 'error', format: winston.format.simple() }), + new winston.transports.Console({ + level: 'error', + format: winston.format.combine(winston.format.colorize({ all: true,colors:{ error: 'red'} }), winston.format.simple()), + }), ], levels: { error: 0 }, }); diff --git a/packages/contentstack-import/README.md b/packages/contentstack-import/README.md index 4085b99023..a8a729c125 100644 --- a/packages/contentstack-import/README.md +++ b/packages/contentstack-import/README.md @@ -47,7 +47,7 @@ $ npm install -g @contentstack/cli-cm-import $ csdx COMMAND running command... $ csdx (--version) -@contentstack/cli-cm-import/1.5.8 darwin-x64 node-v18.16.0 +@contentstack/cli-cm-import/1.5.9 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND @@ -159,5 +159,9 @@ EXAMPLES $ csdx cm:stacks:import --branch --yes ``` +_Mangement token and config file: [example_config/management_config.json](https://github.com/contentstack/cli/blob/main/packages/contentstack-import/example_config/management_config.json)_ + +_Auth token and config file: [example_config/auth_config.json](https://github.com/contentstack/cli/blob/main/packages/contentstack-import/example_config/auth_config.json)_ + _See code: [src/commands/cm/stacks/import.js](https://github.com/contentstack/cli/blob/main/packages/contentstack-import/src/commands/cm/stacks/import.js)_ diff --git a/packages/contentstack-import/example_config/auth_config.json b/packages/contentstack-import/example_config/auth_config.json new file mode 100644 index 0000000000..8a595ff0d3 --- /dev/null +++ b/packages/contentstack-import/example_config/auth_config.json @@ -0,0 +1,16 @@ +{ + "master_locale": { + "name": "English - United States", + "code": "en-us" + }, + "data": "file path", + "target_stack":"bltXXXXXXXXXX", + "branchName":"example1", + "moduleName": "content-types", + "concurrency": 1, + "importConcurrency": 5, + "fetchConcurrency": 5, + "writeConcurrency": 5, + "securedAssets":false, + "developerHubBaseUrl": "" +} diff --git a/packages/contentstack-import/example_config/management_config.json b/packages/contentstack-import/example_config/management_config.json new file mode 100644 index 0000000000..7d56aa34bd --- /dev/null +++ b/packages/contentstack-import/example_config/management_config.json @@ -0,0 +1,15 @@ +{ + "master_locale": { + "name": "English - United States", + "code": "en-us" + }, + "data": "file path", + "branchName":"example1", + "moduleName": "content-types", + "concurrency": 1, + "importConcurrency": 5, + "fetchConcurrency": 5, + "writeConcurrency": 5, + "securedAssets":false, + "developerHubBaseUrl": "" +} diff --git a/packages/contentstack-import/package.json b/packages/contentstack-import/package.json index af9265f4fe..8d4355ff9c 100644 --- a/packages/contentstack-import/package.json +++ b/packages/contentstack-import/package.json @@ -1,12 +1,12 @@ { "name": "@contentstack/cli-cm-import", "description": "Contentstack CLI plugin to import content into stack", - "version": "1.5.8", + "version": "1.5.9", "author": "Contentstack", "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/config": "^1.18.3", "big-json": "^3.2.0", "bluebird": "^3.7.2", diff --git a/packages/contentstack-import/src/app.js b/packages/contentstack-import/src/app.js index 41cae0e164..e57903d477 100755 --- a/packages/contentstack-import/src/app.js +++ b/packages/contentstack-import/src/app.js @@ -47,13 +47,13 @@ exports.initial = (configData) => { importRes.then(resolve).catch(reject); }) .catch((error) => { - addlogs(config, `Failed to import contents ${util.formatError(error)}`, 'error'); + addlogs(config, `Failed to import contents. ${util.formatError(error)}`, 'error'); reject(error); process.exit(1); }); } else { let filename = path.basename(config.data); - addlogs(config, chalk.red(filename + ' Folder does not Exist'), 'error'); + addlogs(config, chalk.red(`'${filename}' Folder does not exist'`), 'error'); } }; @@ -95,7 +95,7 @@ let singleImport = async (APIClient, stackAPIClient, moduleName, types, config) } } if (!(importResponse && importResponse.empty)) { - addlogs(config, moduleName + ' imported successfully!', 'success'); + addlogs(config, `Module '${moduleName}' imported successfully!`, 'success'); } addlogs(config, 'The log for this is stored at ' + path.join(config.oldPath, 'logs', 'import'), 'success'); return true; @@ -103,9 +103,9 @@ let singleImport = async (APIClient, stackAPIClient, moduleName, types, config) addlogs(config, 'Please provide valid module name.', 'error'); } } catch (error) { - addlogs(config, 'Failed to migrate ' + moduleName, 'error'); + addlogs(config, `Failed to migrate '${moduleName}'`, 'error'); addlogs(config, util.formatError(error), 'error'); - addlogs(config, 'The log for this is stored at ' + path.join(config.oldPath, 'logs', 'import'), 'error'); + addlogs(config, `The log for this is stored at '${path.join(config.oldPath, 'logs', 'import')}'`, 'error'); } }; @@ -148,15 +148,11 @@ let allImport = async (APIClient, stackAPIClient, config, types) => { } catch (error) { addlogs( config, - chalk.red( - 'Failed to migrate stack: ' + - (config.destinationStackName || config.target_stack) + - '. Please check error logs for more info', - ), + `Failed to migrate stack '${(config.destinationStackName || config.target_stack)}'. Please check error logs for more info`, 'error', ); addlogs(config, util.formatError(error), 'error'); - addlogs(config, 'The log for this is stored at ' + path.join(config.oldPath, 'logs', 'import'), 'error'); + addlogs(config, `The log for this is stored at '${path.join(config.oldPath, 'logs', 'import')}'`, 'error'); } }; @@ -193,8 +189,8 @@ const validateIfBranchExist = async (stackAPIClient, config, branch) => { .catch((_err) => {}); if (data && typeof data === 'object') { if (data.error_message) { - addlogs(config, chalk.red(data.error_message), 'error'); - addlogs(config, chalk.red('No branch found with the name ' + branch), 'error'); + addlogs(config, data.error_message, 'error'); + addlogs(config, `No branch found with the name '${branch}`, 'error'); reject({ message: 'No branch found with the name ' + branch, error: error_message }); } else { resolve(data); @@ -203,7 +199,7 @@ const validateIfBranchExist = async (stackAPIClient, config, branch) => { reject({ message: 'No branch found with the name ' + branch, error: {} }); } } catch (error) { - addlogs(config, chalk.red('No branch found with the name ' + branch), 'error'); + addlogs(config, `No branch found with the name '${branch}`, 'error'); reject({ message: 'No branch found with the name ' + branch, error }); } }); diff --git a/packages/contentstack-import/src/commands/cm/stacks/import.js b/packages/contentstack-import/src/commands/cm/stacks/import.js index b7a0591678..575dc0e16a 100644 --- a/packages/contentstack-import/src/commands/cm/stacks/import.js +++ b/packages/contentstack-import/src/commands/cm/stacks/import.js @@ -1,7 +1,7 @@ const _ = require('lodash'); const defaultConfig = require('../../../config/default'); const { Command } = require('@contentstack/cli-command'); -const { flags, printFlagDeprecation, isAuthenticated } = require('@contentstack/cli-utilities'); +const { flags, printFlagDeprecation, isAuthenticated, cliux } = require('@contentstack/cli-utilities'); const { configWithMToken, parameterWithMToken, @@ -51,7 +51,7 @@ class ImportCommand extends Command { result.then(resolve).catch(reject); } else { - console.log('management Token is not present please add managment token first'); + cliux.print(`error: management Token is not present please add managment token first`, {color: 'red'}); } } else if (isAuthenticated()) { let result; @@ -66,7 +66,7 @@ class ImportCommand extends Command { result.then(resolve).catch(reject); } else { - console.log('Login or provide the alias for management token'); + cliux.print(`error: Login or provide the alias for management token`, {color: 'red'}); } }); } diff --git a/packages/contentstack-import/src/lib/import/assets.js b/packages/contentstack-import/src/lib/import/assets.js index d3bea00153..e76fc7bb88 100755 --- a/packages/contentstack-import/src/lib/import/assets.js +++ b/packages/contentstack-import/src/lib/import/assets.js @@ -97,7 +97,7 @@ module.exports = class ImportAssets { // hence, upload each asset with its version if (self.config.versioning) { return self.uploadVersionedAssets(assetUid, currentAssetFolderPath).catch(function (error) { - addlogs(self.config, (chalk.red('Asset upload failed \n' + error), 'error')); + addlogs(self.config, `Asset upload failed.\n ${error}`, 'error'); }); } @@ -111,7 +111,7 @@ module.exports = class ImportAssets { } else { addlogs( self.config, - self.assets[assetUid].parent_uid + " parent_uid was not found! Thus, setting it as 'null'", + `'${self.assets[assetUid].parent_uid}' parent_uid was not found! Thus, setting it as 'null'`, 'error', ); } @@ -135,13 +135,13 @@ module.exports = class ImportAssets { // log them onto /mapper/assets/success.json }) .catch(function (error) { - addlogs(self.config, chalk.red('Asset upload failed \n' + error, 'error')); + addlogs(self.config, `Asset upload failed.\n ${error}`, 'error'); return error; // asset failed to upload // log them onto /mapper/assets/fail.json }); } - addlogs(self.config, currentAssetFolderPath + ' does not exist!', 'error'); + addlogs(self.config, `'${currentAssetFolderPath}' does not exist!`, 'error'); }, { concurrency: self.assetConfig.assetBatchLimit }, ).then(function () { @@ -195,7 +195,8 @@ module.exports = class ImportAssets { } else { addlogs( self.config, - (lastVersion.parent_uid + " parent_uid was not found! Thus, setting it as 'null'", 'error'), + `'${lastVersion.parent_uid}' parent_uid was not found! Thus, setting it as 'null'`, + 'error' ); versionedAssetMetadata.forEach(function (assetMetadata) { assetMetadata.parent_uid = null; @@ -247,7 +248,7 @@ module.exports = class ImportAssets { .catch(function (error) { // failed to upload asset // write it on fail logs, but do not stop the process - addlogs(self.config, chalk.red('Failed to upload asset\n' + error), 'error'); + addlogs(self.config, `Failed to upload asset\n ${error}`, 'error'); return resolve(); }); }); @@ -377,7 +378,7 @@ module.exports = class ImportAssets { .catch(function (err) { let error = JSON.parse(err.message); if (error.errors.authorization || error.errors.api_key) { - addlogs(self.config, chalk.red('Api_key or management_token is not valid'), 'error'); + addlogs(self.config, 'Api_key or management_token is not valid', 'error'); return reject(error); } @@ -483,7 +484,7 @@ module.exports = class ImportAssets { error = { errorMessage: err.message }; } - addlogs(self.config, chalk.red('Asset ' + assetUid + ' not published, ' + error.errorMessage), 'error'); + addlogs(self.config, `Asset '${assetUid}' not published, ${error.errorMessage}`, 'error'); return reject(err); } diff --git a/packages/contentstack-import/src/lib/import/content-types.js b/packages/contentstack-import/src/lib/import/content-types.js index ca2e28603d..94bb42c044 100755 --- a/packages/contentstack-import/src/lib/import/content-types.js +++ b/packages/contentstack-import/src/lib/import/content-types.js @@ -106,12 +106,24 @@ class ContentTypesImport { try { await fileHelper.writeFile(path.join(this.contentTypesFolderPath, 'field_rules_uid.json'), this.fieldRules); } catch (error) { - addlogs(this.importConfig, `Failed to write field rules ${formatError(error)}`, 'success'); + addlogs(this.importConfig, `Failed to write field rules ${formatError(error)}`, 'error'); } } addlogs(this.importConfig, chalk.green('Content types imported successfully'), 'success'); } catch (error) { + let message_content_type = ""; + if (error.request !== undefined && JSON.parse(error.request.data).content_type !== undefined) { + if (JSON.parse(error.request.data).content_type.uid) { + message_content_type = + ' Update the content type with content_type_uid - ' + JSON.parse(error.request.data).content_type.uid; + } else if (JSON.parse(error.request.data).content_type.title) { + message_content_type = + ' Update the content type with content_type_title - ' + JSON.parse(error.request.data).content_type.title; + } + error.errorMessage = error.errorMessage + message_content_type; + } + addlogs(this.importConfig, formatError(error.errorMessage), 'error'); addlogs(this.importConfig, formatError(error), 'error'); throw new Error('Failed to import content types'); } @@ -149,7 +161,7 @@ class ContentTypesImport { const contentTypeResponse = this.stackAPIClient.contentType(contentType.uid); Object.assign(contentTypeResponse, cloneDeep(contentType)); await contentTypeResponse.update(); - addlogs(this.importConfig, contentType.uid + ' updated with references', 'success'); + addlogs(this.importConfig, `'${contentType.uid}' updated with references`, 'success'); } async updateGlobalFields(uid) { @@ -167,15 +179,15 @@ class ContentTypesImport { // Improve write the updated global fields once all updates are completed this.existingGlobalFields.splice(existingGlobalField, 1, globalField); await fileHelper.writeFile(this.globalFieldMapperFolderPath, this.existingGlobalFields).catch((error) => { - addlogs(this.importConfig, `failed to write updated the global field ${uid} ${formatError(error)}`); + addlogs(this.importConfig, `failed to write updated the global field '${uid}'. ${formatError(error)}`); }); - addlogs(this.importConfig, `Updated the global field ${uid} with content type references `); + addlogs(this.importConfig, `Updated the global field '${uid}' with content type references `); return true; } catch (error) { - addlogs(this.importConfig, `failed to update the global field ${uid} ${formatError(error)}`); + addlogs(this.importConfig, `failed to update the global field '${uid}'. ${formatError(error)}`); } } else { - addlogs(this.importConfig, `Global field ${uid} does not exist, and hence failed to update.`); + addlogs(this.importConfig, `Global field '${uid}' does not exist, and hence failed to update.`); } } diff --git a/packages/contentstack-import/src/lib/import/custom-roles.js b/packages/contentstack-import/src/lib/import/custom-roles.js index b1068ca89e..b05c734042 100644 --- a/packages/contentstack-import/src/lib/import/custom-roles.js +++ b/packages/contentstack-import/src/lib/import/custom-roles.js @@ -49,7 +49,7 @@ module.exports = class ImportCustomRoles { mkdirp.sync(customRolesMapperPath); if (!self.customRoles) { - addlogs(self.config, chalk.white('No custom-roles found'), 'error'); + addlogs(self.config, chalk.white('No custom-roles found'), 'info'); return; } self.customRolesUids = Object.keys(self.customRoles); @@ -71,7 +71,7 @@ module.exports = class ImportCustomRoles { if (uid in self.customRolesUidMapper) { addlogs( self.config, - chalk.white(`The custom-role ${customRole.name} already exists. Skipping it to avoid duplicates!`), + chalk.white(`The custom-role '${customRole.name}' already exists. Skipping it to avoid duplicates!`), 'success', ); continue; @@ -98,14 +98,13 @@ module.exports = class ImportCustomRoles { self.fails.push(customRole); if (((error && error.errors && error.errors.name) || '').includes('is not a unique.')) { - addlogs(self.config, chalk.red(`${customRole.name} role already exists`), 'info'); + addlogs(self.config, `custom-role '${customRole.name}' already exists`, 'error'); } else { if (!(error && error.errors && error.errors.name)) { - addlogs(self.config, chalk.red(`custom-role: ${customRole.name} already exists`), 'error'); + addlogs(self.config, `custom-role '${customRole.name}' already exists`, 'error'); } else { - addlogs(self.config, chalk.red(`custom-role: ${customRole.name} failed`), 'error'); + addlogs(self.config, `custom-role '${customRole.name}' failed`, 'error'); } - addlogs(self.config, formatError(error), 'error'); } } @@ -113,7 +112,7 @@ module.exports = class ImportCustomRoles { addlogs(self.config, chalk.green('Custom-roles have been imported successfully!'), 'success'); } catch (error) { helper.writeFileSync(customRolesFailsPath, self.fails); - addlogs(self.config, chalk.red('Custom-roles import failed'), 'error'); + addlogs(self.config, 'Custom-roles import failed', 'error'); addlogs(self.config, formatError(error), 'error'); throw error; diff --git a/packages/contentstack-import/src/lib/import/entries.js b/packages/contentstack-import/src/lib/import/entries.js index 153036ddcb..8f749a9f19 100755 --- a/packages/contentstack-import/src/lib/import/entries.js +++ b/packages/contentstack-import/src/lib/import/entries.js @@ -103,7 +103,7 @@ module.exports = class ImportEntries { } } } catch (error) { - addlogs(this.config, `Failed to read the content types to import entries ${util.formatError(error)}`); + addlogs(this.config, `Failed to read the content types to import entries ${util.formatError(error)}`, 'error'); process.exit(0); } } @@ -148,7 +148,7 @@ module.exports = class ImportEntries { (self.config.hasOwnProperty('onlylocales') && self.config.onlylocales.indexOf(lang) !== -1) || !self.config.hasOwnProperty('onlylocales') ) { - addlogs(self.config, `Starting to create entries ${lang} locale`, 'info'); + addlogs(self.config, `Starting to create entries '${lang}' locale`, 'info'); await self.createEntries(lang, mappedAssetUids, mappedAssetUrls); addlogs(self.config, 'Entries created successfully', 'info'); try { @@ -156,7 +156,8 @@ module.exports = class ImportEntries { } catch (error) { addlogs( self.config, - `Failed get the existing entries to update the mapper ${util.formatError(error)}, 'error`, + `Failed get the existing entries to update the mapper ${util.formatError(error)}`, + 'error', ); } addlogs(self.config, 'Starting to update entries with references', 'info'); @@ -164,7 +165,7 @@ module.exports = class ImportEntries { addlogs(self.config, "Successfully imported '" + lang + "' entries!", 'success'); counter++; } else { - addlogs(self.config, lang + ' has not been configured for import, thus skipping it', 'success'); + addlogs(self.config,`'${lang}' has not been configured for import, thus skipping it`, 'success'); counter++; } }, @@ -189,7 +190,8 @@ module.exports = class ImportEntries { } catch (error) { addlogs( self.config, - `Failed to update the field rules for content type ${schema.uid} ${util.formatError(error)}`, + `Failed to update the field rules for content type '${schema.uid}' ${util.formatError(error)}`, + 'error' ); } } @@ -254,7 +256,7 @@ module.exports = class ImportEntries { 'success', ); } else { - addlogs(this.config, `Creating entries for content type ${ctUid} in language ${lang} ...`, 'success'); + addlogs(this.config, `Creating entries for content type '${ctUid}' in language '${lang}' ...`, 'success'); for (let eUid in entries) { if (eUid) { try { @@ -281,7 +283,7 @@ module.exports = class ImportEntries { self.installedExtensions, ); } catch (error) { - addlogs(this.config, 'Failed to update entry while creating entry id ' + eUid); + addlogs(this.config, `Failed to update entry while creating entry id '${eUid}'`, 'error'); addlogs(this.config, util.formatError(error), 'error'); } } @@ -479,13 +481,7 @@ module.exports = class ImportEntries { } else { addlogs( this.config, - chalk.white( - 'Unable to find entry file path for ' + - ctUid + - " content type!\nThe file '" + - eFilePath + - "' does not exist!", - ), + `Unable to find entry file path for '${ctUid}' content type!\nThe file '${eFilePath}' does not exist!`, 'error', ); } @@ -499,7 +495,7 @@ module.exports = class ImportEntries { return resolve(); }) .catch((error) => { - addlogs(this.config, chalk.red("Failed to create entries in '" + lang + "' language"), 'error'); + addlogs(this.config, `Failed to create entries in '${lang}' language`, 'error'); return reject(error); }); }); @@ -568,7 +564,7 @@ module.exports = class ImportEntries { // map failed reference uids @mapper/language/unmapped-uids.json let refUidMapperPath = path.join(this.entryMapperPath, lang); - addlogs(this.config, 'staring to update the entry for reposting'); + addlogs(this.config, 'Starting to update the entry for reposting'); entries = _.map(entries, (entry) => { try { @@ -598,6 +594,7 @@ module.exports = class ImportEntries { addlogs( this.config, `Failed to update the entry ${uid} references while reposting ${util.formatError(error)}`, + 'error' ); } }); @@ -645,14 +642,7 @@ module.exports = class ImportEntries { .catch((error) => { addlogs( this.config, - chalk.red( - 'Entry Uid: ' + - entry.uid + - ' of Content Type: ' + - ctUid + - ' failed to update in locale: ' + - lang, - ), + `Entry Uid '${entry.uid}' of Content Type '${ctUid}' failed to update in locale '${lang}'`, 'error', ); @@ -685,7 +675,7 @@ module.exports = class ImportEntries { }) .catch((error) => { // error while executing entry in batch - addlogs(this.config, chalk.red('Failed re-post entries at batch no: ' + (index + 1)), 'error'); + addlogs(this.config, `Failed re-post entries at batch no: '${(index + 1)}`, 'error'); addlogs(this.config, util.formatError(error), 'error'); // throw error; }); @@ -706,7 +696,8 @@ module.exports = class ImportEntries { // error while updating entries with references addlogs( this.config, - chalk.red(`Failed re-post entries of content type ${ctUid} locale ${lang}`, 'error'), + `Failed re-post entries of content type ${ctUid} locale ${lang}`, + 'error', ); addlogs(this.config, util.formatError(error), 'error'); // throw error; @@ -723,7 +714,7 @@ module.exports = class ImportEntries { }) .catch((error) => { // error while updating entry references - addlogs(this.config, chalk.red('Failed to re post entries in ' + lang + ' language'), 'error'); + addlogs(this.config, `Failed to re post entries in '${lang}' language`, 'error'); return reject(error); }); }); @@ -792,9 +783,9 @@ module.exports = class ImportEntries { .then((_updatedcontentType) => { // empty function }) - .catch((_error) => { + .catch((error) => { addlogs(this.config, util.formatError(error), 'error'); - reject(`Failed suppress content type ${schema.uid} reference fields`); + reject(`Failed suppress content type '${schema.uid}' reference fields`); }); // update 5 content types at a time }, @@ -890,7 +881,7 @@ module.exports = class ImportEntries { return resolveContentType(); }) .catch((error) => { - addlogs(this.config, chalk.red('Failed to re-update ' + schema.uid), 'error'); + addlogs(this.config, `Failed to re-update '${schema.uid}`, 'error'); addlogs(this.config, error, 'error'); return rejectContentType(error); }); @@ -951,7 +942,7 @@ module.exports = class ImportEntries { addlogs(this.config, 'Removed bugged entry from master ' + JSON.stringify(entry), 'success'); }) .catch((error) => { - addlogs(this.config, chalk.red('Failed to remove bugged entry from master language'), 'error'); + addlogs(this.config, 'Failed to remove bugged entry from master language', 'error'); addlogs(this.config, util.formatError(error), 'error'); }); }, @@ -976,6 +967,7 @@ module.exports = class ImportEntries { .catch((error) => { // error while removing bugged entries from stack addlogs(this.config, util.formatError(error), 'error'); + addlogs(this.config, error, 'error'); }); }); } @@ -1057,7 +1049,7 @@ module.exports = class ImportEntries { } else { return; } - + return Promise.map( batches, async (batch, index) => { @@ -1097,7 +1089,7 @@ module.exports = class ImportEntries { // addlogs(this.config, 'Entry ' + eUid + ' published successfully in ' + ctUid + ' content type', 'success') addlogs( this.config, - 'Entry ' + eUid + ' published successfully in ' + ctUid + ' content type', + `Entry '${eUid}' published successfully in '${ctUid}' content type`, 'success', ); return resolveEntryPublished(result); @@ -1106,7 +1098,8 @@ module.exports = class ImportEntries { .catch((err) => { addlogs( this.config, - `failed to publish entry ${eUid} content type ${ctUid} ${util.formatError(err)}`, + `failed to publish entry '${eUid}' content type '${ctUid}' ${util.formatError(err)}`, + 'error' ); return resolveEntryPublished(''); }); @@ -1126,6 +1119,7 @@ module.exports = class ImportEntries { .catch((error) => { // error while executing entry in batch addlogs(this.config, util.formatError(error), 'error'); + addlogs(this.config, error, 'error'); }); }, { @@ -1134,10 +1128,10 @@ module.exports = class ImportEntries { ) .then(() => { // addlogs(this.config, 'Entries published successfully in ' + ctUid + ' content type', 'success') - addlogs('Entries published successfully in ' + ctUid + ' content type'); + addlogs(this.config, `Entries published successfully in '${ctUid}' content type`, 'info'); }) .catch((error) => { - addlogs(this.config, `failed to publish entry in content type ${ctUid} ${util.formatError(error)}`); + addlogs(this.config, `failed to publish entry in content type '${ctUid}' ${util.formatError(error)}`, 'error'); }); }, { @@ -1149,7 +1143,7 @@ module.exports = class ImportEntries { // addlogs('Published entries successfully in ' +); }) .catch((error) => { - addlogs(`Failed to publish few entries in ${lang} ${util.formatError(error)}`); + addlogs(this.config, `Failed to publish few entries in '${lang}' ${util.formatError(error)}`, 'error'); }); }, { @@ -1160,7 +1154,7 @@ module.exports = class ImportEntries { return resolve(); }) .catch((error) => { - addlogs(`Failed to publish entries ${util.formatError(error)}`); + addlogs(this.config,`Failed to publish entries. ${util.formatError(error)}`, 'error'); }); }); } diff --git a/packages/contentstack-import/src/lib/import/environments.js b/packages/contentstack-import/src/lib/import/environments.js index a17142902c..8a648f9302 100755 --- a/packages/contentstack-import/src/lib/import/environments.js +++ b/packages/contentstack-import/src/lib/import/environments.js @@ -71,13 +71,11 @@ module.exports = class ImportEnvironments { let error = JSON.parse(err.message); if (error.errors.name) { - addlogs(self.config, chalk.white("Environment: '" + env.name + "' already exists"), 'error'); + addlogs(self.config, `Environment '${env.name}' already exists`, 'error'); } else { addlogs( config, - chalk.white( - "Environment: '" + env.name + "' failed to be import\n " + JSON.stringify(error.errors), - ), + `Environment '${env.name}' failed to be import\n ${JSON.stringify(error.errors)}`, 'error', ); } @@ -86,7 +84,7 @@ module.exports = class ImportEnvironments { // the environment has already been created addlogs( config, - chalk.white("The environment: '" + env.name + "' already exists. Skipping it to avoid duplicates!"), + `The environment ${env.name} already exists. Skipping it to avoid duplicates!`, 'success', ); } @@ -100,7 +98,7 @@ module.exports = class ImportEnvironments { }) .catch(function (error) { helper.writeFileSync(envFailsPath, self.fails); - addlogs(self.config, chalk.red(`Failed to import environment ${formatError(error)}`), 'error'); + addlogs(self.config, `Failed to import environment, ${formatError(error)}`, 'error'); reject(error); }); }); diff --git a/packages/contentstack-import/src/lib/import/extensions.js b/packages/contentstack-import/src/lib/import/extensions.js index c2de51fd4c..2431346962 100644 --- a/packages/contentstack-import/src/lib/import/extensions.js +++ b/packages/contentstack-import/src/lib/import/extensions.js @@ -69,11 +69,11 @@ module.exports = class ImportExtensions { let error = JSON.parse(err.message); self.fails.push(ext); if (error.errors.title) { - addlogs(self.config, chalk.white("Extension: '" + ext.title + "' already exists"), 'success'); + addlogs(self.config, `Extension '${ext.title}' already exists`, 'error'); } else { addlogs( config, - chalk.white("Extension: '" + ext.title + "' failed to be import\n " + JSON.stringify(error.errors)), + chalk.white(`Extension '${ext.title}' failed to be import\n ${JSON.stringify(error.errors)}`), 'error', ); } @@ -100,7 +100,7 @@ module.exports = class ImportExtensions { .catch(function (error) { // error while importing extensions helper.writeFileSync(extFailsPath, self.fails); - addlogs(self.config, chalk.red(`Extension import failed ${util.formatError(error)}`), 'error'); + addlogs(self.config, `Extension import failed ${util.formatError(error)}`, 'error'); reject(error); }); }); diff --git a/packages/contentstack-import/src/lib/import/global-fields.js b/packages/contentstack-import/src/lib/import/global-fields.js index 5fad020447..6d3c2456ca 100644 --- a/packages/contentstack-import/src/lib/import/global-fields.js +++ b/packages/contentstack-import/src/lib/import/global-fields.js @@ -65,11 +65,11 @@ module.exports = class ImportGlobalFields { let snipUids = Object.keys(self.globalfields); return Promise.map( snipUids, - function (snipUid) { + async function (snipUid) { let flag = { supressed: false }; let snip = self.globalfields[snipUid]; extension_supress(snip.schema, self.config.preserveStackVersion, self.installedExtensions); - removeReferenceFields(snip.schema, flag); + await removeReferenceFields(snip.schema, flag, self.stackAPIClient); if (flag.supressed) { // eslint-disable-next-line no-undef @@ -96,9 +96,9 @@ module.exports = class ImportGlobalFields { let error = JSON.parse(err.message); if (error.errors.title) { // eslint-disable-next-line no-undef - addlogs(self.config, chalk.white(snip.uid + ' globalfield already exists'), 'error'); + addlogs(self.config, `Globalfield '${snip.uid} already exists'`, 'error'); } else { - addlogs(self.config, chalk.red(`Globalfield failed to import ${formatError(error)}`), 'error'); + addlogs(self.config, `Globalfield failed to import ${formatError(error)}`, 'error'); } self.fails.push(snip); @@ -119,7 +119,7 @@ module.exports = class ImportGlobalFields { // globalfields have imported successfully helper.writeFileSync(globalfieldsSuccessPath, self.success); helper.writeFileSync(globalFieldsPending, _globalField_pending); - addlogs(self.config, chalk.green('globalfields have been imported successfully!'), 'success'); + addlogs(self.config, chalk.green('Globalfields have been imported successfully!'), 'success'); return resolve(); }) .catch(function (err) { @@ -127,7 +127,7 @@ module.exports = class ImportGlobalFields { // error while importing globalfields addlogs(self.config, err, 'error'); helper.writeFileSync(globalfieldsFailsPath, self.fails); - addlogs(self.config, chalk.red('globalfields import failed'), 'error'); + addlogs(self.config, `Globalfields import failed. ${formatError(err)}`, 'error'); return reject(error); }); }); diff --git a/packages/contentstack-import/src/lib/import/labels.js b/packages/contentstack-import/src/lib/import/labels.js index e3196df310..108048b195 100644 --- a/packages/contentstack-import/src/lib/import/labels.js +++ b/packages/contentstack-import/src/lib/import/labels.js @@ -76,16 +76,16 @@ module.exports = class ImportLabels { .catch(function (error) { self.fails.push(label); if (error.errors.name) { - addlogs(self.config, chalk.red("Label: '" + label.name + "' already exist"), 'error'); + addlogs(self.config,`Label '${label.name}' already exist`, 'error'); } else { - addlogs(self.config, chalk.red("Label: '" + label.name + "' failed to be imported\n"), 'error'); + addlogs(self.config,`Label '${label.name}' failed to be imported\n`, 'error'); } }); } else { // the label has already been created addlogs( self.config, - chalk.white("The label: '" + label.name + "' already exists. Skipping it to avoid duplicates!"), + chalk.white(`The label '${label.name}' already exists. Skipping it to avoid duplicates!'`), 'success', ); } @@ -104,7 +104,7 @@ module.exports = class ImportLabels { return resolve(); }) .catch(function (error) { - addlogs(self.config, chalk.red(`Failed to import label ${formatError(error)}`), 'error'); + addlogs(self.config, `Failed to import label, ${formatError(error)}`, 'error'); // eslint-disable-next-line no-console return reject(error); }); @@ -113,7 +113,7 @@ module.exports = class ImportLabels { // error while importing labels helper.writeFileSync(labelUidMapperPath, self.labelUidMapper); helper.writeFileSync(labelFailsPath, self.fails); - addlogs(self.config, chalk.red(`Failed to import label ${formatError(error)}`), 'error'); + addlogs(self.config, `Failed to import label, ${formatError(error)}`, 'error'); return reject(error); }); }); diff --git a/packages/contentstack-import/src/lib/import/locales.js b/packages/contentstack-import/src/lib/import/locales.js index ba1771181e..c8ea01f4b0 100755 --- a/packages/contentstack-import/src/lib/import/locales.js +++ b/packages/contentstack-import/src/lib/import/locales.js @@ -91,16 +91,20 @@ module.exports = class ImportLanguages { .catch(function (err) { let error = JSON.parse(err.message); if (error.hasOwnProperty('errorCode') && error.errorCode === 247) { - addlogs(self.config, error.errors.code[0], 'success'); + if(error.errors.code){ + addlogs(self.config, error.errors.code[0], 'error'); + }else{ + addlogs(self.config, err, 'error'); + } return err; } self.fails.push(lang); - addlogs(self.config, chalk.red("Language: '" + lang.code + "' failed to be import\n"), 'error'); + addlogs(self.config, `Language '${lang.code}' failed to import\n`, 'error'); addlogs(self.config, formatError(err), 'error'); }); } else { // the language has already been created - addlogs(self.config, chalk.yellow("The language: '" + lang.code + "' already exists."), 'error'); + addlogs(self.config, `The language '${lang.code}' already exists.`, 'error'); } // import 2 languages at a time @@ -124,8 +128,7 @@ module.exports = class ImportLanguages { .catch(function (error) { // error while importing languages helper.writeFileSync(langFailsPath, self.fails); - addlogs(self.config, chalk.red('Language import failed'), 'error'); - addlogs(self.config, formatError(error), 'error'); + addlogs(self.config, `Language import failed. ${formatError(error)}`, 'error'); reject('failed to import Languages'); }); }); diff --git a/packages/contentstack-import/src/lib/import/marketplace-apps.js b/packages/contentstack-import/src/lib/import/marketplace-apps.js index 10ebd477a8..06dabe6e47 100644 --- a/packages/contentstack-import/src/lib/import/marketplace-apps.js +++ b/packages/contentstack-import/src/lib/import/marketplace-apps.js @@ -515,16 +515,21 @@ module.exports = class ImportMarketplaceApps { return Promise.resolve(); } - return this.httpClient - .put(`${this.developerHubBaseUrl}/installations/${uid}`, payload) - .then(({ data }) => { - if (data.message) { - log(this.config, formatError(data.message), 'success'); - } else { - log(this.config, `${app.manifest.name} app config updated successfully.!`, 'success'); - } - }) - .catch((error) => log(this.config, formatError(error), 'error')); + let installation = this.client + .organization(this.config.org_uid) + .app(app.manifest.uid) + .installation(uid) + + installation = Object.assign(installation, payload) + + return installation + .update() + .then(async data => { + if (data) { + log(this.config, `${app.manifest.name} app config updated successfully.!`, 'success'); + } + }) + .catch((error) => log(this.config, formatError(error), 'error')) } validateAppName(name) { diff --git a/packages/contentstack-import/src/lib/import/webhooks.js b/packages/contentstack-import/src/lib/import/webhooks.js index 2a4a323db0..558ad6718c 100644 --- a/packages/contentstack-import/src/lib/import/webhooks.js +++ b/packages/contentstack-import/src/lib/import/webhooks.js @@ -80,7 +80,7 @@ module.exports = class ImportWebhooks { self.fails.push(web); addlogs( self.config, - chalk.red("Webhooks: '" + web.name + "' failed to be import\n" + formatError(error)), + `Webhooks '${web.name}' failed to be import.\n ${formatError(error)}`, 'error', ); }); @@ -105,7 +105,7 @@ module.exports = class ImportWebhooks { .catch(function (error) { // error while importing environments helper.writeFileSync(webFailsPath, self.fails); - addlogs(self.config, chalk.red('Webhooks import failed'), 'error'); + addlogs(self.config, `Webhooks import failed. ${formatError(error)}`, 'error'); return reject(error); }); }); diff --git a/packages/contentstack-import/src/lib/import/workflows.js b/packages/contentstack-import/src/lib/import/workflows.js index 10e8e6e9fe..0da82ee37c 100644 --- a/packages/contentstack-import/src/lib/import/workflows.js +++ b/packages/contentstack-import/src/lib/import/workflows.js @@ -97,7 +97,7 @@ module.exports = class importWorkflows { } catch (error) { addlogs( self.config, - chalk.red('Error while importing workflows roles. ' + formatError(error)), + `Error while importing workflows roles. ${formatError(error)}`, 'error', ); reject({ message: 'Error while importing workflows roles' }); @@ -128,24 +128,22 @@ module.exports = class importWorkflows { .catch(function (error) { self.fails.push(workflow); if (error.errors.name) { - addlogs(self.config, chalk.red("workflow: '" + workflow.name + "' already exist"), 'error'); + addlogs(self.config, `workflow ${workflow.name} already exist`, 'error'); } else if (error.errors['workflow_stages.0.users']) { addlogs( self.config, - chalk.red( - "Failed to import Workflows as you've specified certain roles in the Stage transition and access rules section. We currently don't import roles to the stack.", - ), + "Failed to import Workflows as you've specified certain roles in the Stage transition and access rules section. We currently don't import roles to the stack.", 'error', ); } else { - addlogs(self.config, chalk.red("workflow: '" + workflow.name + "' failed"), 'error'); + addlogs(self.config, `workflow ${workflow.name} failed.`, 'error'); } }); } else { // the workflow has already been created addlogs( self.config, - chalk.white("The Workflows: '" + workflow.name + "' already exists. Skipping it to avoid duplicates!"), + chalk.white( `The Workflows ${workflow.name} already exists. Skipping it to avoid duplicates!`), 'success', ); } @@ -160,8 +158,7 @@ module.exports = class importWorkflows { }) .catch(function (error) { helper.writeFileSync(workflowFailsPath, self.fails); - addlogs(self.config, chalk.red('Workflows import failed'), 'error'); - addlogs(self.config, formatError(error), 'error'); + addlogs(self.config, `Workflows import failed. ${formatError(error)}`, 'error'); return reject(error); }); }); diff --git a/packages/contentstack-import/src/lib/util/log.js b/packages/contentstack-import/src/lib/util/log.js index f39f8dab6b..7108132545 100755 --- a/packages/contentstack-import/src/lib/util/log.js +++ b/packages/contentstack-import/src/lib/util/log.js @@ -91,7 +91,10 @@ function init(_logPath) { errorLogger = winston.createLogger({ transports: [ new winston.transports.File(errorTransport), - new winston.transports.Console({ level: 'error', format: winston.format.simple() }), + new winston.transports.Console({ + level: 'error', + format: winston.format.combine(winston.format.colorize({ all: true, colors:{ error: 'red'} }), winston.format.simple()), + }), ], levels: { error: 0 }, }); diff --git a/packages/contentstack-import/src/lib/util/removeReferenceFields.js b/packages/contentstack-import/src/lib/util/removeReferenceFields.js index 23d3139059..5534251c96 100644 --- a/packages/contentstack-import/src/lib/util/removeReferenceFields.js +++ b/packages/contentstack-import/src/lib/util/removeReferenceFields.js @@ -1,7 +1,7 @@ -var _ = require('lodash'); +const _ = require('lodash'); /* eslint-disable no-empty */ -var removeReferenceFields = (module.exports = function (schema, flag) { +const removeReferenceFields = (module.exports = async function (schema, flag, stackAPIClient) { for (let i = 0; i < schema.length; i++) { if (schema[i].data_type === 'group') { removeReferenceFields(schema[i].schema, flag); @@ -11,27 +11,41 @@ var removeReferenceFields = (module.exports = function (schema, flag) { } } else if (schema[i].data_type === 'reference') { flag.supressed = true; - schema.splice(i, 1); - --i; - if (schema.length < 1) { - schema.push({ - data_type: 'text', - display_name: 'dummyTest', - uid: 'dummy_test', - field_metadata: { - description: '', - default_value: '', - version: 3, - }, - format: '', - error_messages: { + // Check if content-type exists + // If exists, then no change should be required. + let isContentTypeError = false; + for (let j = 0; j < schema[i].reference_to.length; j++) { + try { + await stackAPIClient.contentType(schema[i].reference_to[j]).fetch(); + } catch (error) { + // Else warn and modify the schema object. + isContentTypeError = true; + console.warn(`Content-type ${schema[i].reference_to[j]} does not exist. Removing the field from schema`); + } + } + if (isContentTypeError) { + schema.splice(i, 1); + --i; + if (schema.length < 1) { + schema.push({ + data_type: 'text', + display_name: 'dummyTest', + uid: 'dummy_test', + field_metadata: { + description: '', + default_value: '', + version: 3, + }, format: '', - }, - multiple: false, - mandatory: false, - unique: false, - non_localizable: false, - }); + error_messages: { + format: '', + }, + multiple: false, + mandatory: false, + unique: false, + non_localizable: false, + }); + } } } else if( // handling entry references in json rte schema[i].data_type === 'json' diff --git a/packages/contentstack-launch/README.md b/packages/contentstack-launch/README.md index d1cd6a346f..916d85781b 100755 --- a/packages/contentstack-launch/README.md +++ b/packages/contentstack-launch/README.md @@ -19,7 +19,7 @@ $ npm install -g @contentstack/cli-launch $ csdx COMMAND running command... $ csdx (--version|-v) -@contentstack/cli-launch/1.0.5 darwin-x64 node-v18.16.0 +@contentstack/cli-launch/1.0.6 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-launch/oclif.manifest.json b/packages/contentstack-launch/oclif.manifest.json index 32e99b1f36..a3a21fc239 100644 --- a/packages/contentstack-launch/oclif.manifest.json +++ b/packages/contentstack-launch/oclif.manifest.json @@ -1,5 +1,5 @@ { - "version": "1.0.5", + "version": "1.0.6", "commands": { "launch:base-command": { "id": "launch:base-command", diff --git a/packages/contentstack-launch/package.json b/packages/contentstack-launch/package.json index 0d5abd9b1d..263c8615bd 100755 --- a/packages/contentstack-launch/package.json +++ b/packages/contentstack-launch/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/cli-launch", - "version": "1.0.5", + "version": "1.0.6", "description": "Launch related operations", "author": "Contentstack CLI", "bin": { @@ -18,8 +18,8 @@ ], "dependencies": { "@apollo/client": "^3.7.9", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/plugin-help": "^5", "@oclif/plugin-plugins": "^2.3.2", "@types/express": "^4.17.17", diff --git a/packages/contentstack-migrate-rte/README.md b/packages/contentstack-migrate-rte/README.md index 3100bdfa72..73c96f7943 100644 --- a/packages/contentstack-migrate-rte/README.md +++ b/packages/contentstack-migrate-rte/README.md @@ -16,7 +16,7 @@ $ npm install -g @contentstack/cli-cm-migrate-rte $ csdx COMMAND running command... $ csdx (--version) -@contentstack/cli-cm-migrate-rte/1.4.7 darwin-x64 node-v18.16.0 +@contentstack/cli-cm-migrate-rte/1.4.8 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND @@ -36,8 +36,9 @@ Migration script to migrate content from HTML RTE to JSON RTE ``` USAGE - $ csdx cm:entries:migrate-html-rte [-c ] [-a ] [--content-type ] [--global-field] [-y] [--branch ] - [--html-path --json-path ] [--delay ] [--locale ] [--batch-limit ] + $ csdx cm:entries:migrate-html-rte [-c ] [-a ] [--stack-api-key ] [--content-type ] + [--global-field] [-y] [--branch ] [--html-path --json-path ] [--delay ] [--locale + ] [--batch-limit ] FLAGS -a, --alias= Alias(name) for the management token @@ -52,6 +53,7 @@ FLAGS --html-path= Provide path of HTML RTE to migrate --json-path= Provide path of JSON RTE to migrate --locale= The locale from which entries will be migrated + --stack-api-key= Stack api key to be used DESCRIPTION Migration script to migrate content from HTML RTE to JSON RTE @@ -95,8 +97,9 @@ Migration script to migrate content from HTML RTE to JSON RTE ``` USAGE - $ csdx cm:migrate-rte [-c ] [-a ] [--content-type ] [--global-field] [-y] [--branch ] - [--html-path --json-path ] [--delay ] [--locale ] [--batch-limit ] + $ csdx cm:migrate-rte [-c ] [-a ] [--stack-api-key ] [--content-type ] + [--global-field] [-y] [--branch ] [--html-path --json-path ] [--delay ] [--locale + ] [--batch-limit ] FLAGS -a, --alias= Alias(name) for the management token @@ -111,6 +114,7 @@ FLAGS --html-path= Provide path of HTML RTE to migrate --json-path= Provide path of JSON RTE to migrate --locale= The locale from which entries will be migrated + --stack-api-key= Stack api key to be used DESCRIPTION Migration script to migrate content from HTML RTE to JSON RTE diff --git a/packages/contentstack-migrate-rte/package.json b/packages/contentstack-migrate-rte/package.json index 64f25665e9..a2f778acbb 100644 --- a/packages/contentstack-migrate-rte/package.json +++ b/packages/contentstack-migrate-rte/package.json @@ -1,12 +1,12 @@ { "name": "@contentstack/cli-cm-migrate-rte", "description": "Contentstack CLI plugin to migrate HTML RTE to JSON RTE", - "version": "1.4.7", + "version": "1.4.8", "author": "contentstack", "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@contentstack/json-rte-serializer": "^2.0.2", "collapse-whitespace": "^1.1.7", "chalk": "^4.1.2", diff --git a/packages/contentstack-migrate-rte/src/commands/cm/entries/migrate-html-rte.js b/packages/contentstack-migrate-rte/src/commands/cm/entries/migrate-html-rte.js index d11263b921..b61b69963c 100644 --- a/packages/contentstack-migrate-rte/src/commands/cm/entries/migrate-html-rte.js +++ b/packages/contentstack-migrate-rte/src/commands/cm/entries/migrate-html-rte.js @@ -20,8 +20,13 @@ class JsonMigrationCommand extends Command { if (isEmpty(config.paths)) { throw new Error('No value provided for the "paths" property in config.'); } - const token = getToken(config.alias); - const stackOptions = { token: token, host: this.cmaHost }; + const stackOptions = { host: this.cmaHost }; + if (config.alias) { + stackOptions.token = getToken(config.alias) + } + if (config['stack-api-key']) { + stackOptions.stackApiKey = config['stack-api-key'] + } if (config.branch) stackOptions.branch = config.branch; let stack = await getStack(stackOptions); config.entriesCount = 0; @@ -69,6 +74,10 @@ JsonMigrationCommand.flags = { description: 'Alias(name) for the management token', required: false, }), + 'stack-api-key': flags.string({ + description: 'Stack api key to be used', + required: false, + }), 'content-type': flags.string({ description: 'The content type from which entries will be migrated', required: false, diff --git a/packages/contentstack-migrate-rte/src/lib/util/config_schema.json b/packages/contentstack-migrate-rte/src/lib/util/config_schema.json index c78a44e7b0..81410c98a3 100644 --- a/packages/contentstack-migrate-rte/src/lib/util/config_schema.json +++ b/packages/contentstack-migrate-rte/src/lib/util/config_schema.json @@ -18,7 +18,7 @@ ] } ], - "required": ["alias", "content-type", "paths"], + "required": ["content-type", "paths"], "properties": { "alias": { "$id": "#/properties/alias", @@ -36,6 +36,14 @@ "default": "", "examples": ["test1"] }, + "stack-api-key": { + "$id": "#/properties/stack-api-key", + "type": "string", + "title": "The Stack api key", + "description": "An explanation about the purpose of this instance.", + "default": "", + "examples": ["Migration Test"] + }, "content-type": { "$id": "#/properties/content-type", "type": "string", @@ -71,7 +79,7 @@ "$id": "#/properties/paths/items", "anyOf": [ { - "$id": "#/properties/paths/items/anyOf/0", + "$id": "html-path and json-path are required", "type": "object", "title": "The first anyOf schema", "description": "An explanation about the purpose of this instance.", @@ -248,5 +256,17 @@ "minimum": 1 } }, + "oneOf": [ + { + "type": "object", + "title": "stack-api-key", + "required": ["stack-api-key"] + }, + { + "type": "object", + "title": "alias", + "required": ["alias"] + } + ], "additionalProperties": true } diff --git a/packages/contentstack-migrate-rte/src/lib/util/index.js b/packages/contentstack-migrate-rte/src/lib/util/index.js index d621dc6033..509c0309aa 100644 --- a/packages/contentstack-migrate-rte/src/lib/util/index.js +++ b/packages/contentstack-migrate-rte/src/lib/util/index.js @@ -1,4 +1,3 @@ -const contentstacksdk = require('@contentstack/management'); const { Command } = require('@contentstack/cli-command'); const command = new Command(); const chalk = require('chalk'); @@ -21,24 +20,42 @@ const { JSDOM } = require('jsdom'); const collapseWithSpace = require('collapse-whitespace'); const { htmlToJson } = require('@contentstack/json-rte-serializer'); const nodePath = require('path'); -const { cliux, managementSDKClient } = require('@contentstack/cli-utilities'); +const { cliux, managementSDKClient, isAuthenticated, doesBranchExist } = require('@contentstack/cli-utilities'); const packageValue = require('../../../package.json'); const isBlank = (variable) => { return isNil(variable) || isEmpty(variable); }; async function getStack(data) { - const tokenDetails = data.token; + const stackOptions = {}; const options = { host: data.host, application: `json-rte-migration/${packageValue.version}`, timeout: 120000, }; + if (data.token) { + const tokenDetails = data.token; + stackOptions['api_key'] = tokenDetails.apiKey; + options['management_token'] = tokenDetails.token // need to pass management token so that the sdk doesn't get configured with authtoken (throws error in case of oauth, if the provided stack doesn't belong to the org selected while logging in with oauth) + stackOptions['management_token'] = tokenDetails.token; + } + if (data.stackApiKey) { + if (!isAuthenticated()) { + throw new Error('Please login to proceed further. Or use `--alias` instead of `--stack-api-key` to proceed without logging in.') + } + stackOptions['api_key'] = data.stackApiKey; + } if (data.branch) options.branchName = data.branch; const client = await managementSDKClient(options); - const stack = client.stack({ api_key: tokenDetails.apiKey, management_token: tokenDetails.token }); + const stack = client.stack(stackOptions); stack.host = data.host; + if (data.branch) { + let branchData = await doesBranchExist(stack, data.branch); + if (branchData && branchData.errorCode) { + throw new Error(branchData.errorMessage) + } + } return stack; }; @@ -74,7 +91,6 @@ async function getConfig(flags) { config = require(nodePath.resolve(configPath)); } else { config = { - alias: flags.alias, 'content-type': flags['content-type'], 'global-field': flags['global-field'], paths: [ @@ -92,6 +108,12 @@ async function getConfig(flags) { if (flags.branch) { config.branch = flags['branch']; } + if (flags.alias) { + config.alias = flags.alias + } + if (flags['stack-api-key']) { + config['stack-api-key'] = flags['stack-api-key'] + } } if (checkConfig(config)) { let confirmed = await confirmConfig(config, flags.yes); @@ -152,7 +174,7 @@ function throwConfigError(error) { } function checkConfig(config) { let v = new Validator(); - let res = v.validate(config, configSchema, { throwFirst: true }); + let res = v.validate(config, configSchema, {throwError: true, nestedErrors: true}); return res.valid; } function prettyPrint(data) { diff --git a/packages/contentstack-migration/README.md b/packages/contentstack-migration/README.md index 6c47ff015a..9fa5899da3 100644 --- a/packages/contentstack-migration/README.md +++ b/packages/contentstack-migration/README.md @@ -21,7 +21,7 @@ $ npm install -g @contentstack/cli-migration $ csdx COMMAND running command... $ csdx (--version) -@contentstack/cli-migration/1.3.7 darwin-x64 node-v18.16.0 +@contentstack/cli-migration/1.3.8 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-migration/package.json b/packages/contentstack-migration/package.json index 0377c0407e..4d6f4b3b16 100644 --- a/packages/contentstack-migration/package.json +++ b/packages/contentstack-migration/package.json @@ -1,11 +1,11 @@ { "name": "@contentstack/cli-migration", - "version": "1.3.7", + "version": "1.3.8", "author": "@contentstack", "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "@oclif/command": "^1.8.16", "@oclif/config": "^1.18.3", "async": "^3.2.4", diff --git a/packages/contentstack-seed/package.json b/packages/contentstack-seed/package.json index 39c5af2ba3..801d0f3efa 100644 --- a/packages/contentstack-seed/package.json +++ b/packages/contentstack-seed/package.json @@ -1,13 +1,13 @@ { "name": "@contentstack/cli-cm-seed", "description": "create a Stack from existing content types, entries, assets, etc.", - "version": "1.4.8", + "version": "1.4.9", "author": "Contentstack", "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { - "@contentstack/cli-cm-import": "^1.5.8", - "@contentstack/cli-command": "^1.2.8", - "@contentstack/cli-utilities": "^1.4.4", + "@contentstack/cli-cm-import": "^1.5.9", + "@contentstack/cli-command": "^1.2.9", + "@contentstack/cli-utilities": "^1.4.5", "axios": "1.3.4", "inquirer": "8.2.4", "mkdirp": "^1.0.4", diff --git a/packages/contentstack-utilities/package.json b/packages/contentstack-utilities/package.json index 0bc09ce22d..0b7c9e53a4 100644 --- a/packages/contentstack-utilities/package.json +++ b/packages/contentstack-utilities/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/cli-utilities", - "version": "1.4.4", + "version": "1.4.5", "description": "Utilities for contentstack projects", "main": "lib/index.js", "types": "lib/index.d.ts", @@ -13,7 +13,9 @@ "test": "nyc --extension .ts mocha --forbid-only \"test/**/*.test.ts\"", "posttest": "npm run lint", "lint": "eslint src/**/*.ts", - "format": "eslint src/**/*.ts --fix" + "format": "eslint src/**/*.ts --fix", + "test:unit": "mocha --forbid-only \"test/unit/**/*.test.ts\"", + "test:unit:report": "nyc --extension .ts mocha --forbid-only \"test/unit/**/*.test.ts\"" }, "repository": { "type": "git", @@ -75,4 +77,4 @@ "tslib": "^1.13.0", "typescript": "^4.9.3" } -} +} \ No newline at end of file diff --git a/packages/contentstack-utilities/src/auth-handler.ts b/packages/contentstack-utilities/src/auth-handler.ts index 1df7e614a5..fc104d5ca3 100644 --- a/packages/contentstack-utilities/src/auth-handler.ts +++ b/packages/contentstack-utilities/src/auth-handler.ts @@ -126,9 +126,41 @@ class AuthHandler { `You can review the access permissions on the page - ${this.OAuthBaseURL}/#!/marketplace/authorized-apps`, ); res.writeHead(200, { 'Content-Type': 'text/html' }); - res.end( - `

Successfully authorized!

You can close this window now.

You can review the access permissions on - Authorized Apps page

`, - ); + res.end(` +

Successfully authorized!

+

You can close this window now.

+

+ You can review the access permissions on the + Authorized Apps page. +

`); + stopServer(); }) .catch((error) => { diff --git a/packages/contentstack-utilities/src/helpers.ts b/packages/contentstack-utilities/src/helpers.ts index 08b6e97cfe..600f698c27 100644 --- a/packages/contentstack-utilities/src/helpers.ts +++ b/packages/contentstack-utilities/src/helpers.ts @@ -1,2 +1,10 @@ import authHandler from './auth-handler'; export const isAuthenticated = () => authHandler.isAuthenticated(); +export const doesBranchExist = async (stack, branchName) => { + return stack + .branch(branchName) + .fetch() + .catch((error) => { + return error; + }); +}; diff --git a/packages/contentstack-utilities/test/unit/auth-handler.test.ts b/packages/contentstack-utilities/test/unit/auth-handler.test.ts new file mode 100644 index 0000000000..62de315d65 --- /dev/null +++ b/packages/contentstack-utilities/test/unit/auth-handler.test.ts @@ -0,0 +1,510 @@ +//@ts-nocheck +import { expect } from 'chai'; +import { assert, stub, createSandbox } from 'sinon'; +import { cliux } from '@contentstack/cli-utilities'; +import authHandler from '../../src/auth-handler'; +import configHandler from '../../src/config-handler'; +import { HttpClient } from '../../src/http-client'; +const http = require('http'); +const crypto = require('crypto'); + +describe('Auth Handler', () => { + describe('setOAuthBaseURL', () => { + let sandbox; + + beforeEach(() => { + sandbox = createSandbox(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should set the OAuthBaseURL when a valid uiHost URL is present in the config', async () => { + const expectedURL = 'https://example.com'; + sandbox.stub(configHandler, 'get').returns({ uiHost: expectedURL }); + + await authHandler.setOAuthBaseURL(); + }); + }); + + describe('oauth', () => { + let createHTTPServerStub; + let openOAuthURLStub; + + beforeEach(() => { + createHTTPServerStub = stub(authHandler, 'createHTTPServer'); + openOAuthURLStub = stub(authHandler, 'openOAuthURL'); + }); + + afterEach(() => { + createHTTPServerStub.restore(); + openOAuthURLStub.restore(); + }); + + it('should reject with an error when createHTTPServer fails', async () => { + const expectedErrorMessage = 'Failed to create HTTP server'; + createHTTPServerStub.rejects(new Error(expectedErrorMessage)); + + try { + await authHandler.oauth(); + expect.fail('Expected promise to reject'); + } catch (error) { + expect(error.message).to.equal(expectedErrorMessage); + expect(createHTTPServerStub.calledOnce).to.be.true; + expect(openOAuthURLStub.notCalled).to.be.true; + } + }); + + it('should reject with an error when openOAuthURL fails', async () => { + createHTTPServerStub.resolves(); + openOAuthURLStub.rejects(new Error('Failed to open OAuth URL')); + + try { + await authHandler.oauth(); + expect.fail('Expected promise to reject'); + } catch (error) { + expect(error.message).to.equal('Failed to open OAuth URL'); + expect(createHTTPServerStub.calledOnce).to.be.true; + expect(openOAuthURLStub.calledOnce).to.be.true; + } + }); + + it('should resolve with an empty object when createHTTPServer and openOAuthURL succeed', async () => { + createHTTPServerStub.resolves(); + openOAuthURLStub.resolves(); + + const result = await authHandler.oauth(); + + expect(createHTTPServerStub.calledOnce).to.be.true; + expect(openOAuthURLStub.calledOnce).to.be.true; + expect(result).to.deep.equal({}); + }); + }); + + describe('createHTTPServer', () => { + let sandbox; + beforeEach(() => { + sandbox = createSandbox(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should reject with an error if an error occurs', async () => { + const error = new Error('An error occurred'); + const serverStub = sandbox.stub(http, 'createServer').throws(error); + + sandbox.replace(http, 'createServer', serverStub); + + try { + await authHandler.createHTTPServer(); + expect.fail('Expected an error to be thrown'); + } catch (err) { + expect(err).to.equal(error); + } + }); + }); + + describe('openOAuthURL', () => { + let sandbox, openMock; + beforeEach(() => { + sandbox = createSandbox(); + openMock = sandbox.stub().resolves(); + global.open = openMock; + }); + + afterEach(() => { + delete global.open; + sandbox.restore(); + }); + + it('should open the OAuth URL and resolve with the result', async () => { + const expectedURL = 'https://example.com/oauth'; + const openStub = sandbox.stub().resolves(); + + sandbox.stub(authHandler, 'setOAuthBaseURL').resolves(); + sandbox.stub(crypto, 'createHash').returns({ update: () => {}, digest: () => {} }); + sandbox.stub(authHandler, 'codeVerifier').value('CODE_VERIFIER'); + sandbox.stub(authHandler, 'OAuthBaseURL').value('https://example.com'); + sandbox.stub(authHandler, 'OAuthAppId').value('APP_ID'); + sandbox.stub(authHandler, 'OAuthResponseType').value('response_type'); + sandbox.stub(authHandler, 'OAuthClientId').value('client_id'); + sandbox.stub(authHandler, 'OAuthRedirectURL').value('redirect_uri'); + sandbox.stub(authHandler, 'OAuthScope').value('scope'); + sandbox.stub(cliux, 'print'); + sandbox.stub(cliux, 'error'); + + sandbox.replace(global, 'open', openStub); + + try { + await authHandler.openOAuthURL(); + + assert.calledWith(openStub, expectedURL); + } catch (error) {} + }); + }); + + describe('getAccessToken', () => { + let sandbox; + + beforeEach(() => { + sandbox = createSandbox(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should retrieve access token and set OAuth tokens', async () => { + const code = 'AUTHORIZATION_CODE'; + const accessToken = 'ACCESS_TOKEN'; + const refreshToken = 'REFRESH_TOKEN'; + const userData = { + access_token: accessToken, + refresh_token: refreshToken, + }; + + try { + const expectedPayload = { + grant_type: 'authorization_code', + client_id: authHandler.OAuthClientId, + code_verifier: authHandler.codeVerifier, + redirect_uri: authHandler.OAuthRedirectURL, + code, + }; + + const httpClientStub = sandbox.stub(HttpClient.prototype, 'post').resolves({ data: userData }); + const getUserDetailsStub = sandbox.stub(authHandler, 'getUserDetails').resolves(userData); + const setConfigDataStub = sandbox.stub(authHandler, 'setConfigData').resolves(); + + await authHandler.getAccessToken(code); + + assert.calledWith(httpClientStub, `${authHandler.OAuthBaseURL}/apps-api/apps/token`, expectedPayload); + assert.calledWith(getUserDetailsStub, userData); + assert.calledWith(setConfigDataStub, 'oauth', userData); + } catch (error) {} + }); + }); + + describe('setConfigData', () => { + let sandbox; + + beforeEach(() => { + sandbox = createSandbox(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should set OAuth tokens info when type is "oauth"', async () => { + const userData = { + access_token: 'abc123', + refresh_token: '***REMOVED***', + email: 'test@example.com', + user_uid: 'user123', + organization_uid: 'org123', + }; + try { + sandbox.stub(configHandler, 'set').returns(); + + await authHandler.setConfigData('oauth', userData); + + assert.calledWith(configHandler.set, authHandler.oauthAccessTokenKeyName, userData.access_token); + assert.calledWith(configHandler.set, authHandler.oauthRefreshTokenKeyName, userData.refresh_token); + assert.calledWith(configHandler.set, authHandler.authEmailKeyName, userData.email); + } catch (error) {} + }); + + it('should set refresh token config data', async () => { + const userData = { + access_token: 'abc123', + refresh_token: '***REMOVED***', + }; + + try { + sandbox.stub(configHandler, 'set'); + await authHandler.setConfigData('refreshToken', userData); + + assert.calledWithExactly(setStub, authHandler.oauthAccessTokenKeyName, userData.access_token); + assert.calledWithExactly(setStub, authHandler.oauthRefreshTokenKeyName, userData.refresh_token); + } catch (error) {} + }); + + it('should set basic auth config data', async () => { + const userData = { + authtoken: 'abc123', + email: 'test@example.com', + }; + + try { + sandbox.stub(configHandler, 'set'); + + await authHandler.setConfigData('basicAuth', userData); + + assert.calledWithExactly(setStub, authHandler.authTokenKeyName, userData.authtoken); + assert.calledWithExactly(setStub, authHandler.authEmailKeyName, userData.email); + } catch (error) {} + }); + }); + + describe('unsetConfigData', () => { + let sandbox; + + beforeEach(() => { + sandbox = createSandbox(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should unset the default config data when type is not specified', async () => { + const deleteStub = sandbox.stub(configHandler, 'delete'); + + authHandler.unsetConfigData(); + + assert.callCount(deleteStub, authHandler.allAuthConfigItems.default.length); + authHandler.allAuthConfigItems.default.forEach((item, index) => { + assert.calledWithExactly(deleteStub.getCall(index), item); + }); + }); + + it('should unset the refresh token config data when type is "refreshToken"', async () => { + const deleteStub = sandbox.stub(configHandler, 'delete'); + + authHandler.unsetConfigData('refreshToken'); + + assert.callCount(deleteStub, authHandler.allAuthConfigItems.refreshToken.length); + authHandler.allAuthConfigItems.refreshToken.forEach((item, index) => { + assert.calledWithExactly(deleteStub.getCall(index), item); + }); + }); + }); + + describe('refreshToken', () => { + let sandbox; + + beforeEach(() => { + sandbox = createSandbox(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should refresh the token and resolve with data when refresh token is valid', async () => { + const configOauthRefreshToken = 'valid_refresh_token'; // Set a valid refresh token here + const configAuthorisationType = authHandler.authorisationTypeOAUTHValue; + const expectedData = { + access_token: 'new_access_token', + refresh_token: 'new_refresh_token', + }; + + const postStub = sandbox.stub().resolves({ data: expectedData }); + const httpClientStub = { + post: postStub, + }; + const httpClientInstance = new HttpClient().headers().asFormParams(); + sandbox.stub(httpClientInstance, 'post').value(httpClientStub); + + sandbox.stub(authHandler, 'setConfigData').resolves(expectedData); + + sandbox + .stub(configHandler, 'get') + .withArgs(authHandler.oauthRefreshTokenKeyName) + .returns(configOauthRefreshToken) + .withArgs(authHandler.authorisationTypeKeyName) + .returns(configAuthorisationType); + + authHandler.refreshToken(); + }); + }); + + describe('getUserDetails', () => { + let sandbox; + let managementAPIClientStub; + + beforeEach(() => { + sandbox = createSandbox(); + managementAPIClientStub = sandbox.stub(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should reject with error when access token is invalid/empty', async () => { + const data = { + access_token: 'invalid_access_token', + }; + const expectedError = new Error('The provided access token is invalid or expired or revoked'); + + const getUserStub = sandbox.stub().rejects(expectedError); + managementAPIClientStub.returns({ getUser: getUserStub }); + + authHandler.contentstackManagementSDKClient = managementAPIClientStub; + + authHandler.getUserDetails(data); + }); + + it('should reject with error when access token is invalid/empty', async () => { + const data = { + access_token: '', + }; + + const userDetailsPromise = authHandler.getUserDetails(data); + + return userDetailsPromise.catch((error) => { + expect(error).to.equal('Invalid/Empty access token'); + }); + }); + }); + + describe('isAuthenticated', () => { + let sandbox; + let configHandlerGetStub; + + beforeEach(() => { + sandbox = createSandbox(); + configHandlerGetStub = sandbox.stub(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should return true if the authorization type is OAUTH or AUTH', () => { + const expectedAuthorizationType = 'oauth'; + + configHandlerGetStub.withArgs(authHandler.authorisationTypeKeyName).returns(expectedAuthorizationType); + + authHandler.isAuthenticated(); + }); + }); + + describe('getAuthorisationType', () => { + let sandbox; + let configHandlerGetStub; + + beforeEach(() => { + sandbox = createSandbox(); + configHandlerGetStub = sandbox.stub(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should return the authorization type if it exists in the configuration', async () => { + const expectedAuthorizationType = 'OAUTH'; + + configHandlerGetStub.withArgs(authHandler.authorisationTypeKeyName).returns(expectedAuthorizationType); + + await authHandler.getAuthorisationType(); + }); + }); + + describe('isAuthorisationTypeBasic', () => { + let sandbox; + let configHandlerGetStub; + + beforeEach(() => { + sandbox = createSandbox(); + configHandlerGetStub = sandbox.stub(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should return false if the authorization type is not AUTH', async () => { + const expectedAuthorizationType = 'oauth'; + + configHandlerGetStub.withArgs(authHandler.authorisationTypeKeyName).returns(expectedAuthorizationType); + + await authHandler.isAuthorisationTypeBasic(); + }); + }); + + describe('isAuthorisationTypeOAuth', () => { + let sandbox; + let configHandlerGetStub; + + beforeEach(() => { + sandbox = createSandbox(); + configHandlerGetStub = sandbox.stub(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should return true if the authorization type is OAUTH', async () => { + const expectedAuthorizationType = 'OAUTH'; + + configHandlerGetStub.withArgs(authHandler.authorisationTypeKeyName).returns(expectedAuthorizationType); + + await authHandler.isAuthorisationTypeOAuth(); + }); + }); + + describe('compareOAuthExpiry', () => { + let sandbox; + let configHandlerGetStub; + let cliuxPrintStub; + let refreshTokenStub; + let unsetConfigDataStub; + + beforeEach(() => { + sandbox = createSandbox(); + configHandlerGetStub = sandbox.stub(); + cliuxPrintStub = sandbox.stub(); + refreshTokenStub = sandbox.stub(); + unsetConfigDataStub = sandbox.stub(); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('should resolve if the OAuth token is valid and not expired', async () => { + const expectedOAuthDateTime = '2023-05-30T12:00:00Z'; + const expectedAuthorisationType = 'oauth'; + const now = new Date('2023-05-30T12:30:00Z'); + + configHandlerGetStub.withArgs(authHandler.oauthDateTimeKeyName).returns(expectedOAuthDateTime); + configHandlerGetStub.withArgs(authHandler.authorisationTypeKeyName).returns(expectedAuthorisationType); + + sandbox.stub(Date, 'now').returns(now.getTime()); + + try { + await authHandler.compareOAuthExpiry(); + } catch (error) { + expect(error).to.be.undefined; + expect(cliuxPrintStub.called).to.be.false; + expect(refreshTokenStub.called).to.be.false; + expect(unsetConfigDataStub.called).to.be.false; + } + }); + + it('should resolve if force is true and refreshToken is called', async () => { + const expectedOAuthDateTime = '2023-05-30T12:00:00Z'; + const expectedAuthorisationType = 'oauth'; + + configHandlerGetStub.withArgs(authHandler.oauthDateTimeKeyName).returns(expectedOAuthDateTime); + configHandlerGetStub.withArgs(authHandler.authorisationTypeKeyName).returns(expectedAuthorisationType); + + try { + await authHandler.compareOAuthExpiry(); + } catch (error) { + expect(error).to.be.undefined; + expect(cliuxPrintStub.calledOnceWithExactly('Force refreshing the token')).to.be.true; + expect(refreshTokenStub.calledOnce).to.be.true; + expect(unsetConfigDataStub.called).to.be.false; + } + }); + }); +}); diff --git a/packages/contentstack/README.md b/packages/contentstack/README.md index e1e78bacb7..77242e8510 100644 --- a/packages/contentstack/README.md +++ b/packages/contentstack/README.md @@ -18,7 +18,7 @@ $ npm install -g @contentstack/cli $ csdx COMMAND running command... $ csdx (--version|-v) -@contentstack/cli/1.7.6 darwin-x64 node-v18.16.0 +@contentstack/cli/1.7.7 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND @@ -1300,8 +1300,9 @@ Migration script to migrate content from HTML RTE to JSON RTE ``` USAGE - $ csdx cm:entries:migrate-html-rte [-c ] [-a ] [--content-type ] [--global-field] [-y] [--branch ] - [--html-path --json-path ] [--delay ] [--locale ] [--batch-limit ] + $ csdx cm:entries:migrate-html-rte [-c ] [-a ] [--stack-api-key ] [--content-type ] + [--global-field] [-y] [--branch ] [--html-path --json-path ] [--delay ] [--locale + ] [--batch-limit ] FLAGS -a, --alias= Alias(name) for the management token @@ -1316,6 +1317,7 @@ FLAGS --html-path= Provide path of HTML RTE to migrate --json-path= Provide path of JSON RTE to migrate --locale= The locale from which entries will be migrated + --stack-api-key= Stack api key to be used DESCRIPTION Migration script to migrate content from HTML RTE to JSON RTE @@ -1815,13 +1817,14 @@ Export entries or organization users to csv using this command ``` USAGE $ csdx cm:export-to-csv [--action entries|users] [-a ] [--org ] [-n ] [--org-name ] - [--locale ] [--content-type ] + [--locale ] [--content-type ] [--branch ] FLAGS -a, --alias= Alias of the management token -n, --stack-name= Name of the stack that needs to be created as csv filename. --action=