diff --git a/.talismanrc b/.talismanrc index 69ef0ebca9..4001e0d052 100644 --- a/.talismanrc +++ b/.talismanrc @@ -1,60 +1,6 @@ fileignoreconfig: - - filename: package-lock.json - checksum: 00e4a9ed4b961c39cc2fa0391d3fad67b3e3e6ed9e1ec18de317521951852d84 - filename: pnpm-lock.yaml - checksum: 99f51c8898c4201c5a00cda4564b84713f7d6a77b263199de854bc12bff57552 - - filename: packages/contentstack-import/src/commands/cm/stacks/import.ts - checksum: ee643d664d69eafc6f82923048a85c4dc26f78b1ac93cfe1e152c69945b65d9e - - filename: packages/contentstack-seed/src/commands/cm/stacks/seed.ts - checksum: d04770564196b080878566255ea0faf1c82c1460161d2004d2b1edece0546493 - - filename: packages/contentstack-import/README.md - checksum: f701583669afcf9be38c8b1698aede39658c0df5afe6691ba1301408d20c7c69 - - filename: packages/contentstack-auth/test/unit/commands/tokens-remove.test.ts - checksum: 7e256db86c516b40c47eab78b3881b7ece525607281ebcd0b8711c089bdac056 - - filename: packages/contentstack-export/src/commands/cm/stacks/export.ts - checksum: 0f419db76a2e4132e8f833ae2b194d2c2658a0417265390a6036b63b3401c876 - - filename: packages/contentstack-export/README.md - checksum: ed79c7f29e1cb17a4889c9b19877fd2d7596aec4cc8fcbf4f83643155ef1800c - - filename: packages/contentstack-import-setup/README.md - checksum: f1640c025b0f7603b5f81b511802bf9de18ee6daefbf01521b8d2347490c7757 - - filename: packages/contentstack-import-setup/src/commands/cm/stacks/import-setup.ts - checksum: a903276f842ec00e49ed4751d6df8f4f7213fb1aaa631323f6ce593dad0b236c - - filename: packages/contentstack-migration/README.md - checksum: f25b5601b30057471827d44b41483ea9664586f6c65559ac04a3d39bfb319526 - - filename: packages/contentstack-import-setup/src/utils/login-handler.ts - checksum: ca22ae9649dbc11eba4a4399ef517bdd3f3e3b0ca815307a3313bc9332be3f85 - - filename: packages/contentstack-migration/src/commands/cm/stacks/migration.js - checksum: ebc17ed46356ec89d294fa0caa84a654d09823410ba5f122331c0ebd83decd92 - - filename: packages/contentstack-import-setup/test/unit/login-handler.test.ts - checksum: 51155d629b9825ab8218023cba367ea41264ce534f891e3a6e14a829c2399654 - - filename: packages/contentstack-bootstrap/test/bootstrap-integration.test.js - checksum: d3e3902b2ee72aa41483da5c135e5c4bcec85f65939695708e9bec9478f6336c - - filename: packages/contentstack-migration/test/unit/utils/map.test.js - checksum: 7d570280b2f379531dde84946b06171d50f92489ff0de6336f7fbd81c336ee89 - - filename: packages/contentstack-seed/test/commands/cm/stacks/seed.test.ts - checksum: 61143bbb2ac86c24afc6972d17d9179c6181ec68a909b84570afdad2aaa13ade - - filename: packages/contentstack-config/test/unit/commands/remove-base-branch.test.ts - checksum: 3e73b079b749120221f357d66ac7351ddb300d283f28410d5e6f3b0309ab3962 - - filename: packages/contentstack-migration/test/unit/validators/edit-content-type-validator.test.js - checksum: bde4bc6b2a90e7ce5872e6fbbabef9f2db352705be4d2f8d28d71d84209a714e - - filename: packages/contentstack-bootstrap/test/bootstrap.test.js - checksum: b1f46b3447b1b358f80d6404d9d5b385fb385714e5c1f865ca97d64d6edaefc2 - - filename: packages/contentstack-seed/README.md - checksum: 67378f35a33ae250a8099bbb42a5e644486e7279715685e3ba5c65add6451c46 - - filename: packages/contentstack-utilities/test/unit/contentstack-marketplace-sdk.test.ts - checksum: ccf521d7eafe03d5c4b597c8b30c4cceac00e75d597685fbfb411da4603fbd29 - - filename: packages/contentstack-migration/test/unit/validators/create-content-type-validator.test.js - checksum: f92e39a542cd2d561c441d23395515cadc24c9514de55c3edb038f70bd2458b3 - - filename: packages/contentstack-migration/test/unit/modules/parser.test.js - checksum: 243fa1c45875675f719f660c0c988e2ba9266c562a37aaeb09b0db93a0cb037d - - filename: packages/contentstack-bootstrap/test/interactive.test.js - checksum: fb0c32cd846cce3a53927316699a1c5aaa814939fe9b33bcd9141addbbe447d0 - - filename: packages/contentstack-seed/test/seed/interactive.test.ts - checksum: e7a823051b5eb27f2674ca2c31719205fa822e9cac1524dbd14e48b1ec078c06 - - filename: packages/contentstack/README.md - checksum: e650b0eb54404b08fb2b802a05883dc5984bff43842876df70bcbb5821034fe5 - - filename: packages/contentstack-seed/test/seed/importer.test.ts - checksum: 77bc27f5217c6d69c21bac51afc94d677ad67374c1b39b0575646300eb0decd3 - - filename: packages/contentstack-seed/test/seed/contentstack/client.test.ts - checksum: f1bc369c9c3c4a84ddd590864c0f3e8b13be956b8fb8891b6324f44cdcc7d568 -version: '1.0' + checksum: 41bc1d60449ab0682d9267172e54a5802c837869a1728b0560eea8052336c2fe + - filename: package-lock.json + checksum: 134104853f260380025e0d7e2b49ec32f15a1832b20756676819ce0bc4277c44 +version: "1.0" diff --git a/package-lock.json b/package-lock.json index ff06f3f16d..245b8192ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -280,46 +280,46 @@ } }, "node_modules/@aws-sdk/client-cloudfront": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudfront/-/client-cloudfront-3.971.0.tgz", - "integrity": "sha512-kLtm5jaWVXaej8a6WbFd1iDMFXy19WakT8b/hk3gHtcm6KfnTGX1K/YwpNGfuTzUze16ZjQrbIen/loM+2U2KA==", + "version": "3.974.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudfront/-/client-cloudfront-3.974.0.tgz", + "integrity": "sha512-QAuQjcXGhPuXl7y2OxcJxS0Rz9UmDPQl1ay6+mfXEH7+KQ7rLIzimBkDPlaKd9eNI9yR3XqjZWQyHQEfaBHIlw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.970.0", - "@aws-sdk/credential-provider-node": "3.971.0", - "@aws-sdk/middleware-host-header": "3.969.0", - "@aws-sdk/middleware-logger": "3.969.0", - "@aws-sdk/middleware-recursion-detection": "3.969.0", - "@aws-sdk/middleware-user-agent": "3.970.0", - "@aws-sdk/region-config-resolver": "3.969.0", - "@aws-sdk/types": "3.969.0", - "@aws-sdk/util-endpoints": "3.970.0", - "@aws-sdk/util-user-agent-browser": "3.969.0", - "@aws-sdk/util-user-agent-node": "3.971.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/credential-provider-node": "^3.972.1", + "@aws-sdk/middleware-host-header": "^3.972.1", + "@aws-sdk/middleware-logger": "^3.972.1", + "@aws-sdk/middleware-recursion-detection": "^3.972.1", + "@aws-sdk/middleware-user-agent": "^3.972.1", + "@aws-sdk/region-config-resolver": "^3.972.1", + "@aws-sdk/types": "^3.973.0", + "@aws-sdk/util-endpoints": "3.972.0", + "@aws-sdk/util-user-agent-browser": "^3.972.1", + "@aws-sdk/util-user-agent-node": "^3.972.1", "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.20.6", + "@smithy/core": "^3.21.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.7", - "@smithy/middleware-retry": "^4.4.23", + "@smithy/middleware-endpoint": "^4.4.10", + "@smithy/middleware-retry": "^4.4.26", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.8", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.10.8", + "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.22", - "@smithy/util-defaults-mode-node": "^4.2.25", + "@smithy/util-defaults-mode-browser": "^4.3.25", + "@smithy/util-defaults-mode-node": "^4.2.28", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -333,35 +333,35 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.971.0.tgz", - "integrity": "sha512-BBUne390fKa4C4QvZlUZ5gKcu+Uyid4IyQ20N4jl0vS7SK2xpfXlJcgKqPW5ts6kx6hWTQBk6sH5Lf12RvuJxg==", + "version": "3.974.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.974.0.tgz", + "integrity": "sha512-X+vpXNJ8cU8Iw1FtDgDHxo9z6RxlXfcTtpdGnKws4rk+tCYKSAor/DG6BRMzbh4E5xAA7DiU1Ny3BTrRRSt/Yg==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha1-browser": "5.2.0", "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.970.0", - "@aws-sdk/credential-provider-node": "3.971.0", - "@aws-sdk/middleware-bucket-endpoint": "3.969.0", - "@aws-sdk/middleware-expect-continue": "3.969.0", - "@aws-sdk/middleware-flexible-checksums": "3.971.0", - "@aws-sdk/middleware-host-header": "3.969.0", - "@aws-sdk/middleware-location-constraint": "3.969.0", - "@aws-sdk/middleware-logger": "3.969.0", - "@aws-sdk/middleware-recursion-detection": "3.969.0", - "@aws-sdk/middleware-sdk-s3": "3.970.0", - "@aws-sdk/middleware-ssec": "3.971.0", - "@aws-sdk/middleware-user-agent": "3.970.0", - "@aws-sdk/region-config-resolver": "3.969.0", - "@aws-sdk/signature-v4-multi-region": "3.970.0", - "@aws-sdk/types": "3.969.0", - "@aws-sdk/util-endpoints": "3.970.0", - "@aws-sdk/util-user-agent-browser": "3.969.0", - "@aws-sdk/util-user-agent-node": "3.971.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/credential-provider-node": "^3.972.1", + "@aws-sdk/middleware-bucket-endpoint": "^3.972.1", + "@aws-sdk/middleware-expect-continue": "^3.972.1", + "@aws-sdk/middleware-flexible-checksums": "^3.972.1", + "@aws-sdk/middleware-host-header": "^3.972.1", + "@aws-sdk/middleware-location-constraint": "^3.972.1", + "@aws-sdk/middleware-logger": "^3.972.1", + "@aws-sdk/middleware-recursion-detection": "^3.972.1", + "@aws-sdk/middleware-sdk-s3": "^3.972.1", + "@aws-sdk/middleware-ssec": "^3.972.1", + "@aws-sdk/middleware-user-agent": "^3.972.1", + "@aws-sdk/region-config-resolver": "^3.972.1", + "@aws-sdk/signature-v4-multi-region": "3.972.0", + "@aws-sdk/types": "^3.973.0", + "@aws-sdk/util-endpoints": "3.972.0", + "@aws-sdk/util-user-agent-browser": "^3.972.1", + "@aws-sdk/util-user-agent-node": "^3.972.1", "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.20.6", + "@smithy/core": "^3.21.0", "@smithy/eventstream-serde-browser": "^4.2.8", "@smithy/eventstream-serde-config-resolver": "^4.3.8", "@smithy/eventstream-serde-node": "^4.2.8", @@ -372,21 +372,21 @@ "@smithy/invalid-dependency": "^4.2.8", "@smithy/md5-js": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.7", - "@smithy/middleware-retry": "^4.4.23", + "@smithy/middleware-endpoint": "^4.4.10", + "@smithy/middleware-retry": "^4.4.26", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.8", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.10.8", + "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.22", - "@smithy/util-defaults-mode-node": "^4.2.25", + "@smithy/util-defaults-mode-browser": "^4.3.25", + "@smithy/util-defaults-mode-node": "^4.2.28", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -400,45 +400,45 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.971.0.tgz", - "integrity": "sha512-Xx+w6DQqJxDdymYyIxyKJnRzPvVJ4e/Aw0czO7aC9L/iraaV7AG8QtRe93OGW6aoHSh72CIiinnpJJfLsQqP4g==", + "version": "3.974.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.974.0.tgz", + "integrity": "sha512-ci+GiM0c4ULo4D79UMcY06LcOLcfvUfiyt8PzNY0vbt5O8BfCPYf4QomwVgkNcLLCYmroO4ge2Yy1EsLUlcD6g==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.970.0", - "@aws-sdk/middleware-host-header": "3.969.0", - "@aws-sdk/middleware-logger": "3.969.0", - "@aws-sdk/middleware-recursion-detection": "3.969.0", - "@aws-sdk/middleware-user-agent": "3.970.0", - "@aws-sdk/region-config-resolver": "3.969.0", - "@aws-sdk/types": "3.969.0", - "@aws-sdk/util-endpoints": "3.970.0", - "@aws-sdk/util-user-agent-browser": "3.969.0", - "@aws-sdk/util-user-agent-node": "3.971.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/middleware-host-header": "^3.972.1", + "@aws-sdk/middleware-logger": "^3.972.1", + "@aws-sdk/middleware-recursion-detection": "^3.972.1", + "@aws-sdk/middleware-user-agent": "^3.972.1", + "@aws-sdk/region-config-resolver": "^3.972.1", + "@aws-sdk/types": "^3.973.0", + "@aws-sdk/util-endpoints": "3.972.0", + "@aws-sdk/util-user-agent-browser": "^3.972.1", + "@aws-sdk/util-user-agent-node": "^3.972.1", "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.20.6", + "@smithy/core": "^3.21.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.7", - "@smithy/middleware-retry": "^4.4.23", + "@smithy/middleware-endpoint": "^4.4.10", + "@smithy/middleware-retry": "^4.4.26", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.8", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.10.8", + "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.22", - "@smithy/util-defaults-mode-node": "^4.2.25", + "@smithy/util-defaults-mode-browser": "^4.3.25", + "@smithy/util-defaults-mode-node": "^4.2.28", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -450,20 +450,20 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.970.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.970.0.tgz", - "integrity": "sha512-klpzObldOq8HXzDjDlY6K8rMhYZU6mXRz6P9F9N+tWnjoYFfeBMra8wYApydElTUYQKP1O7RLHwH1OKFfKcqIA==", + "version": "3.973.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.973.0.tgz", + "integrity": "sha512-qy3Fmt8z4PRInM3ZqJmHihQ2tfCdj/MzbGaZpuHjYjgl1/Gcar4Pyp/zzHXh9hGEb61WNbWgsJcDUhnGIiX1TA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.969.0", - "@aws-sdk/xml-builder": "3.969.0", - "@smithy/core": "^3.20.6", + "@aws-sdk/types": "^3.973.0", + "@aws-sdk/xml-builder": "^3.972.1", + "@smithy/core": "^3.21.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", - "@smithy/smithy-client": "^4.10.8", + "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/util-base64": "^4.3.0", "@smithy/util-middleware": "^4.2.8", @@ -475,9 +475,9 @@ } }, "node_modules/@aws-sdk/crc64-nvme": { - "version": "3.969.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/crc64-nvme/-/crc64-nvme-3.969.0.tgz", - "integrity": "sha512-IGNkP54HD3uuLnrPCYsv3ZD478UYq+9WwKrIVJ9Pdi3hxPg8562CH3ZHf8hEgfePN31P9Kj+Zu9kq2Qcjjt61A==", + "version": "3.972.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/crc64-nvme/-/crc64-nvme-3.972.0.tgz", + "integrity": "sha512-ThlLhTqX68jvoIVv+pryOdb5coP1cX1/MaTbB9xkGDCbWbsqQcLqzPxuSoW1DCnAAIacmXCWpzUNOB9pv+xXQw==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -489,14 +489,14 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.970.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.970.0.tgz", - "integrity": "sha512-rtVzXzEtAfZBfh+lq3DAvRar4c3jyptweOAJR2DweyXx71QSMY+O879hjpMwES7jl07a3O1zlnFIDo4KP/96kQ==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.1.tgz", + "integrity": "sha512-/etNHqnx96phy/SjI0HRC588o4vKH5F0xfkZ13yAATV7aNrb+5gYGNE6ePWafP+FuZ3HkULSSlJFj0AxgrAqYw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.970.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" @@ -506,19 +506,19 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.970.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.970.0.tgz", - "integrity": "sha512-CjDbWL7JxjLc9ZxQilMusWSw05yRvUJKRpz59IxDpWUnSMHC9JMMUUkOy5Izk8UAtzi6gupRWArp4NG4labt9Q==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.1.tgz", + "integrity": "sha512-AeopObGW5lpWbDRZ+t4EAtS7wdfSrHPLeFts7jaBzgIaCCD7TL7jAyAB9Y5bCLOPF+17+GL54djCCsjePljUAw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.970.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/types": "^3.973.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/node-http-handler": "^4.4.8", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.10.8", + "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/util-stream": "^4.5.10", "tslib": "^2.6.2" @@ -528,21 +528,21 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.971.0.tgz", - "integrity": "sha512-c0TGJG4xyfTZz3SInXfGU8i5iOFRrLmy4Bo7lMyH+IpngohYMYGYl61omXqf2zdwMbDv+YJ9AviQTcCaEUKi8w==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.972.1.tgz", + "integrity": "sha512-OdbJA3v+XlNDsrYzNPRUwr8l7gw1r/nR8l4r96MDzSBDU8WEo8T6C06SvwaXR8SpzsjO3sq5KMP86wXWg7Rj4g==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.970.0", - "@aws-sdk/credential-provider-env": "3.970.0", - "@aws-sdk/credential-provider-http": "3.970.0", - "@aws-sdk/credential-provider-login": "3.971.0", - "@aws-sdk/credential-provider-process": "3.970.0", - "@aws-sdk/credential-provider-sso": "3.971.0", - "@aws-sdk/credential-provider-web-identity": "3.971.0", - "@aws-sdk/nested-clients": "3.971.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/credential-provider-env": "^3.972.1", + "@aws-sdk/credential-provider-http": "^3.972.1", + "@aws-sdk/credential-provider-login": "^3.972.1", + "@aws-sdk/credential-provider-process": "^3.972.1", + "@aws-sdk/credential-provider-sso": "^3.972.1", + "@aws-sdk/credential-provider-web-identity": "^3.972.1", + "@aws-sdk/nested-clients": "3.974.0", + "@aws-sdk/types": "^3.973.0", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -554,15 +554,15 @@ } }, "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.971.0.tgz", - "integrity": "sha512-yhbzmDOsk0RXD3rTPhZra4AWVnVAC4nFWbTp+sUty1hrOPurUmhuz8bjpLqYTHGnlMbJp+UqkQONhS2+2LzW2g==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.1.tgz", + "integrity": "sha512-CccqDGL6ZrF3/EFWZefvKW7QwwRdxlHUO8NVBKNVcNq6womrPDvqB6xc9icACtE0XB0a7PLoSTkAg8bQVkTO2w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.970.0", - "@aws-sdk/nested-clients": "3.971.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/nested-clients": "3.974.0", + "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -574,19 +574,19 @@ } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.971.0.tgz", - "integrity": "sha512-epUJBAKivtJqalnEBRsYIULKYV063o/5mXNJshZfyvkAgNIzc27CmmKRXTN4zaNOZg8g/UprFp25BGsi19x3nQ==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.1.tgz", + "integrity": "sha512-DwXPk9GfuU/xG9tmCyXFVkCr6X3W8ZCoL5Ptb0pbltEx1/LCcg7T+PBqDlPiiinNCD6ilIoMJDWsnJ8ikzZA7Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "3.970.0", - "@aws-sdk/credential-provider-http": "3.970.0", - "@aws-sdk/credential-provider-ini": "3.971.0", - "@aws-sdk/credential-provider-process": "3.970.0", - "@aws-sdk/credential-provider-sso": "3.971.0", - "@aws-sdk/credential-provider-web-identity": "3.971.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/credential-provider-env": "^3.972.1", + "@aws-sdk/credential-provider-http": "^3.972.1", + "@aws-sdk/credential-provider-ini": "^3.972.1", + "@aws-sdk/credential-provider-process": "^3.972.1", + "@aws-sdk/credential-provider-sso": "^3.972.1", + "@aws-sdk/credential-provider-web-identity": "^3.972.1", + "@aws-sdk/types": "^3.973.0", "@smithy/credential-provider-imds": "^4.2.8", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -598,14 +598,14 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.970.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.970.0.tgz", - "integrity": "sha512-0XeT8OaT9iMA62DFV9+m6mZfJhrD0WNKf4IvsIpj2Z7XbaYfz3CoDDvNoALf3rPY9NzyMHgDxOspmqdvXP00mw==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.1.tgz", + "integrity": "sha512-bi47Zigu3692SJwdBvo8y1dEwE6B61stCwCFnuRWJVTfiM84B+VTSCV661CSWJmIZzmcy7J5J3kWyxL02iHj0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.970.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", @@ -616,16 +616,16 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.971.0.tgz", - "integrity": "sha512-dY0hMQ7dLVPQNJ8GyqXADxa9w5wNfmukgQniLxGVn+dMRx3YLViMp5ZpTSQpFhCWNF0oKQrYAI5cHhUJU1hETw==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.972.1.tgz", + "integrity": "sha512-dLZVNhM7wSgVUFsgVYgI5hb5Z/9PUkT46pk/SHrSmUqfx6YDvoV4YcPtaiRqviPpEGGiRtdQMEadyOKIRqulUQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/client-sso": "3.971.0", - "@aws-sdk/core": "3.970.0", - "@aws-sdk/token-providers": "3.971.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/client-sso": "3.974.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/token-providers": "3.974.0", + "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", @@ -636,15 +636,15 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.971.0.tgz", - "integrity": "sha512-F1AwfNLr7H52T640LNON/h34YDiMuIqW/ZreGzhRR6vnFGaSPtNSKAKB2ssAMkLM8EVg8MjEAYD3NCUiEo+t/w==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.1.tgz", + "integrity": "sha512-YMDeYgi0u687Ay0dAq/pFPKuijrlKTgsaB/UATbxCs/FzZfMiG4If5ksywHmmW7MiYUF8VVv+uou3TczvLrN4w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.970.0", - "@aws-sdk/nested-clients": "3.971.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/nested-clients": "3.974.0", + "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", @@ -655,14 +655,14 @@ } }, "node_modules/@aws-sdk/middleware-bucket-endpoint": { - "version": "3.969.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.969.0.tgz", - "integrity": "sha512-MlbrlixtkTVhYhoasblKOkr7n2yydvUZjjxTnBhIuHmkyBS1619oGnTfq/uLeGYb4NYXdeQ5OYcqsRGvmWSuTw==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.972.1.tgz", + "integrity": "sha512-YVvoitBdE8WOpHqIXvv49efT73F4bJ99XH2bi3Dn3mx7WngI4RwHwn/zF5i0q1Wdi5frGSCNF3vuh+pY817//w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.969.0", - "@aws-sdk/util-arn-parser": "3.968.0", + "@aws-sdk/types": "^3.973.0", + "@aws-sdk/util-arn-parser": "^3.972.1", "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", @@ -674,13 +674,13 @@ } }, "node_modules/@aws-sdk/middleware-expect-continue": { - "version": "3.969.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.969.0.tgz", - "integrity": "sha512-qXygzSi8osok7tH9oeuS3HoKw6jRfbvg5Me/X5RlHOvSSqQz8c5O9f3MjUApaCUSwbAU92KrbZWasw2PKiaVHg==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.972.1.tgz", + "integrity": "sha512-6lfl2/J/kutzw/RLu1kjbahsz4vrGPysrdxWaw8fkjLYG+6M6AswocIAZFS/LgAVi/IWRwPTx9YC0/NH2wDrSw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.969.0", + "@aws-sdk/types": "^3.973.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" @@ -690,18 +690,18 @@ } }, "node_modules/@aws-sdk/middleware-flexible-checksums": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.971.0.tgz", - "integrity": "sha512-+hGUDUxeIw8s2kkjfeXym0XZxdh0cqkHkDpEanWYdS1gnWkIR+gf9u/DKbKqGHXILPaqHXhWpLTQTVlaB4sI7Q==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.972.1.tgz", + "integrity": "sha512-kjVVREpqeUkYQsXr78AcsJbEUlxGH7+H6yS7zkjrnu6HyEVxbdSndkKX6VpKneFOihjCAhIXlk4wf3butDHkNQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/crc32": "5.2.0", "@aws-crypto/crc32c": "5.2.0", "@aws-crypto/util": "5.2.0", - "@aws-sdk/core": "3.970.0", - "@aws-sdk/crc64-nvme": "3.969.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/crc64-nvme": "3.972.0", + "@aws-sdk/types": "^3.973.0", "@smithy/is-array-buffer": "^4.2.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", @@ -716,13 +716,13 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.969.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.969.0.tgz", - "integrity": "sha512-AWa4rVsAfBR4xqm7pybQ8sUNJYnjyP/bJjfAw34qPuh3M9XrfGbAHG0aiAfQGrBnmS28jlO6Kz69o+c6PRw1dw==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.1.tgz", + "integrity": "sha512-/R82lXLPmZ9JaUGSUdKtBp2k/5xQxvBT3zZWyKiBOhyulFotlfvdlrO8TnqstBimsl4lYEYySDL+W6ldFh6ALg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.969.0", + "@aws-sdk/types": "^3.973.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" @@ -732,13 +732,13 @@ } }, "node_modules/@aws-sdk/middleware-location-constraint": { - "version": "3.969.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.969.0.tgz", - "integrity": "sha512-zH7pDfMLG/C4GWMOpvJEoYcSpj7XsNP9+irlgqwi667sUQ6doHQJ3yyDut3yiTk0maq1VgmriPFELyI9lrvH/g==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.972.1.tgz", + "integrity": "sha512-YisPaCbvBk9gY5aUI8jDMDKXsLZ9Fet0WYj1MviK8tZYMgxBIYHM6l3O/OHaAIujojZvamd9F3haYYYWp5/V3w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.969.0", + "@aws-sdk/types": "^3.973.0", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, @@ -747,13 +747,13 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.969.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.969.0.tgz", - "integrity": "sha512-xwrxfip7Y2iTtCMJ+iifN1E1XMOuhxIHY9DreMCvgdl4r7+48x2S1bCYPWH3eNY85/7CapBWdJ8cerpEl12sQQ==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.972.1.tgz", + "integrity": "sha512-JGgFl6cHg9G2FHu4lyFIzmFN8KESBiRr84gLC3Aeni0Gt1nKm+KxWLBuha/RPcXxJygGXCcMM4AykkIwxor8RA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.969.0", + "@aws-sdk/types": "^3.973.0", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, @@ -762,13 +762,13 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.969.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.969.0.tgz", - "integrity": "sha512-2r3PuNquU3CcS1Am4vn/KHFwLi8QFjMdA/R+CRDXT4AFO/0qxevF/YStW3gAKntQIgWgQV8ZdEtKAoJvLI4UWg==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.972.1.tgz", + "integrity": "sha512-taGzNRe8vPHjnliqXIHp9kBgIemLE/xCaRTMH1NH0cncHeaPcjxtnCroAAM9aOlPuKvBe2CpZESyvM1+D8oI7Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.969.0", + "@aws-sdk/types": "^3.973.0", "@aws/lambda-invoke-store": "^0.2.2", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", @@ -779,20 +779,20 @@ } }, "node_modules/@aws-sdk/middleware-sdk-s3": { - "version": "3.970.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.970.0.tgz", - "integrity": "sha512-v/Y5F1lbFFY7vMeG5yYxuhnn0CAshz6KMxkz1pDyPxejNE9HtA0w8R6OTBh/bVdIm44QpjhbI7qeLdOE/PLzXQ==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.1.tgz", + "integrity": "sha512-q/hK0ZNf/aafFRv2wIlDM3p+izi5cXwktVNvRvW646A0MvVZmT4/vwadv/jPA9AORFbnpyf/0luxiMz181f9yg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.970.0", - "@aws-sdk/types": "3.969.0", - "@aws-sdk/util-arn-parser": "3.968.0", - "@smithy/core": "^3.20.6", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/types": "^3.973.0", + "@aws-sdk/util-arn-parser": "^3.972.1", + "@smithy/core": "^3.21.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", - "@smithy/smithy-client": "^4.10.8", + "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/util-config-provider": "^4.2.0", "@smithy/util-middleware": "^4.2.8", @@ -805,13 +805,13 @@ } }, "node_modules/@aws-sdk/middleware-ssec": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.971.0.tgz", - "integrity": "sha512-QGVhvRveYG64ZhnS/b971PxXM6N2NU79Fxck4EfQ7am8v1Br0ctoeDDAn9nXNblLGw87we9Z65F7hMxxiFHd3w==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.972.1.tgz", + "integrity": "sha512-fLtRTPd/MxJT2drJKft2GVGKm35PiNEeQ1Dvz1vc/WhhgAteYrp4f1SfSgjgLaYWGMExESJL4bt8Dxqp6tVsog==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.969.0", + "@aws-sdk/types": "^3.973.0", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, @@ -820,16 +820,16 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.970.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.970.0.tgz", - "integrity": "sha512-dnSJGGUGSFGEX2NzvjwSefH+hmZQ347AwbLhAsi0cdnISSge+pcGfOFrJt2XfBIypwFe27chQhlfuf/gWdzpZg==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.1.tgz", + "integrity": "sha512-6SVg4pY/9Oq9MLzO48xuM3lsOb8Rxg55qprEtFRpkUmuvKij31f5SQHEGxuiZ4RqIKrfjr2WMuIgXvqJ0eJsPA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.970.0", - "@aws-sdk/types": "3.969.0", - "@aws-sdk/util-endpoints": "3.970.0", - "@smithy/core": "^3.20.6", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/types": "^3.973.0", + "@aws-sdk/util-endpoints": "3.972.0", + "@smithy/core": "^3.21.0", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" @@ -839,45 +839,45 @@ } }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.971.0.tgz", - "integrity": "sha512-TWaILL8GyYlhGrxxnmbkazM4QsXatwQgoWUvo251FXmUOsiXDFDVX3hoGIfB3CaJhV2pJPfebHUNJtY6TjZ11g==", + "version": "3.974.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.974.0.tgz", + "integrity": "sha512-k3dwdo/vOiHMJc9gMnkPl1BA5aQfTrZbz+8fiDkWrPagqAioZgmo5oiaOaeX0grObfJQKDtcpPFR4iWf8cgl8Q==", "dev": true, "license": "Apache-2.0", "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.970.0", - "@aws-sdk/middleware-host-header": "3.969.0", - "@aws-sdk/middleware-logger": "3.969.0", - "@aws-sdk/middleware-recursion-detection": "3.969.0", - "@aws-sdk/middleware-user-agent": "3.970.0", - "@aws-sdk/region-config-resolver": "3.969.0", - "@aws-sdk/types": "3.969.0", - "@aws-sdk/util-endpoints": "3.970.0", - "@aws-sdk/util-user-agent-browser": "3.969.0", - "@aws-sdk/util-user-agent-node": "3.971.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/middleware-host-header": "^3.972.1", + "@aws-sdk/middleware-logger": "^3.972.1", + "@aws-sdk/middleware-recursion-detection": "^3.972.1", + "@aws-sdk/middleware-user-agent": "^3.972.1", + "@aws-sdk/region-config-resolver": "^3.972.1", + "@aws-sdk/types": "^3.973.0", + "@aws-sdk/util-endpoints": "3.972.0", + "@aws-sdk/util-user-agent-browser": "^3.972.1", + "@aws-sdk/util-user-agent-node": "^3.972.1", "@smithy/config-resolver": "^4.4.6", - "@smithy/core": "^3.20.6", + "@smithy/core": "^3.21.0", "@smithy/fetch-http-handler": "^5.3.9", "@smithy/hash-node": "^4.2.8", "@smithy/invalid-dependency": "^4.2.8", "@smithy/middleware-content-length": "^4.2.8", - "@smithy/middleware-endpoint": "^4.4.7", - "@smithy/middleware-retry": "^4.4.23", + "@smithy/middleware-endpoint": "^4.4.10", + "@smithy/middleware-retry": "^4.4.26", "@smithy/middleware-serde": "^4.2.9", "@smithy/middleware-stack": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/node-http-handler": "^4.4.8", "@smithy/protocol-http": "^5.3.8", - "@smithy/smithy-client": "^4.10.8", + "@smithy/smithy-client": "^4.10.11", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-base64": "^4.3.0", "@smithy/util-body-length-browser": "^4.2.0", "@smithy/util-body-length-node": "^4.2.1", - "@smithy/util-defaults-mode-browser": "^4.3.22", - "@smithy/util-defaults-mode-node": "^4.2.25", + "@smithy/util-defaults-mode-browser": "^4.3.25", + "@smithy/util-defaults-mode-node": "^4.2.28", "@smithy/util-endpoints": "^3.2.8", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -889,13 +889,13 @@ } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.969.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.969.0.tgz", - "integrity": "sha512-scj9OXqKpcjJ4jsFLtqYWz3IaNvNOQTFFvEY8XMJXTv+3qF5I7/x9SJtKzTRJEBF3spjzBUYPtGFbs9sj4fisQ==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.1.tgz", + "integrity": "sha512-voIY8RORpxLAEgEkYaTFnkaIuRwVBEc+RjVZYcSSllPV+ZEKAacai6kNhJeE3D70Le+JCfvRb52tng/AVHY+jQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.969.0", + "@aws-sdk/types": "^3.973.0", "@smithy/config-resolver": "^4.4.6", "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", @@ -906,17 +906,110 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.970.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.970.0.tgz", - "integrity": "sha512-z3syXfuK/x/IsKf/AeYmgc2NT7fcJ+3fHaGO+fkghkV9WEba3fPyOwtTBX4KpFMNb2t50zDGZwbzW1/5ighcUQ==", + "version": "3.972.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.972.0.tgz", + "integrity": "sha512-2udiRijmjpN81Pvajje4TsjbXDZNP6K9bYUanBYH8hXa/tZG5qfGCySD+TyX0sgDxCQmEDMg3LaQdfjNHBDEgQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/middleware-sdk-s3": "3.972.0", + "@aws-sdk/types": "3.972.0", + "@smithy/protocol-http": "^5.3.8", + "@smithy/signature-v4": "^5.3.8", + "@smithy/types": "^4.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@aws-sdk/core": { + "version": "3.972.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.972.0.tgz", + "integrity": "sha512-nEeUW2M9F+xdIaD98F5MBcQ4ITtykj3yKbgFZ6J0JtL3bq+Z90szQ6Yy8H/BLPYXTs3V4n9ifnBo8cprRDiE6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "3.972.0", + "@aws-sdk/xml-builder": "3.972.0", + "@smithy/core": "^3.20.6", + "@smithy/node-config-provider": "^4.3.8", + "@smithy/property-provider": "^4.2.8", + "@smithy/protocol-http": "^5.3.8", + "@smithy/signature-v4": "^5.3.8", + "@smithy/smithy-client": "^4.10.8", + "@smithy/types": "^4.12.0", + "@smithy/util-base64": "^4.3.0", + "@smithy/util-middleware": "^4.2.8", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@aws-sdk/middleware-sdk-s3": { + "version": "3.972.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.972.0.tgz", + "integrity": "sha512-0bcKFXWx+NZ7tIlOo7KjQ+O2rydiHdIQahrq+fN6k9Osky29v17guy68urUKfhTobR6iY6KvxkroFWaFtTgS5w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-sdk-s3": "3.970.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/core": "3.972.0", + "@aws-sdk/types": "3.972.0", + "@aws-sdk/util-arn-parser": "3.972.0", + "@smithy/core": "^3.20.6", + "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/signature-v4": "^5.3.8", + "@smithy/smithy-client": "^4.10.8", "@smithy/types": "^4.12.0", + "@smithy/util-config-provider": "^4.2.0", + "@smithy/util-middleware": "^4.2.8", + "@smithy/util-stream": "^4.5.10", + "@smithy/util-utf8": "^4.2.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@aws-sdk/types": { + "version": "3.972.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.972.0.tgz", + "integrity": "sha512-U7xBIbLSetONxb2bNzHyDgND3oKGoIfmknrEVnoEU4GUSs+0augUOIn9DIWGUO2ETcRFdsRUnmx9KhPT9Ojbug==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@aws-sdk/util-arn-parser": { + "version": "3.972.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.972.0.tgz", + "integrity": "sha512-RM5Mmo/KJ593iMSrALlHEOcc9YOIyOsDmS5x2NLOMdEmzv1o00fcpAkCQ02IGu1eFneBFT7uX0Mpag0HI+Cz2g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@aws-sdk/xml-builder": { + "version": "3.972.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.0.tgz", + "integrity": "sha512-POaGMcXnozzqBUyJM3HLUZ9GR6OKJWPGJEmhtTnxZXt8B6JcJ/6K3xRJ5H/j8oovVLz8Wg6vFxAHv8lvuASxMg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.12.0", + "fast-xml-parser": "5.2.5", "tslib": "^2.6.2" }, "engines": { @@ -924,15 +1017,15 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.971.0.tgz", - "integrity": "sha512-4hKGWZbmuDdONMJV0HJ+9jwTDb0zLfKxcCLx2GEnBY31Gt9GeyIQ+DZ97Bb++0voawj6pnZToFikXTyrEq2x+w==", + "version": "3.974.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.974.0.tgz", + "integrity": "sha512-cBykL0LiccKIgNhGWvQRTPvsBLPZxnmJU3pYxG538jpFX8lQtrCy1L7mmIHNEdxIdIGEPgAEHF8/JQxgBToqUQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "3.970.0", - "@aws-sdk/nested-clients": "3.971.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/core": "^3.973.0", + "@aws-sdk/nested-clients": "3.974.0", + "@aws-sdk/types": "^3.973.0", "@smithy/property-provider": "^4.2.8", "@smithy/shared-ini-file-loader": "^4.4.3", "@smithy/types": "^4.12.0", @@ -943,9 +1036,9 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.969.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.969.0.tgz", - "integrity": "sha512-7IIzM5TdiXn+VtgPdVLjmE6uUBUtnga0f4RiSEI1WW10RPuNvZ9U+pL3SwDiRDAdoGrOF9tSLJOFZmfuwYuVYQ==", + "version": "3.973.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.973.0.tgz", + "integrity": "sha512-jYIdB7a7jhRTvyb378nsjyvJh1Si+zVduJ6urMNGpz8RjkmHZ+9vM2H07XaIB2Cfq0GhJRZYOfUCH8uqQhqBkQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -957,9 +1050,9 @@ } }, "node_modules/@aws-sdk/util-arn-parser": { - "version": "3.968.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.968.0.tgz", - "integrity": "sha512-gqqvYcitIIM2K4lrDX9de9YvOfXBcVdxfT/iLnvHJd4YHvSXlt+gs+AsL4FfPCxG4IG9A+FyulP9Sb1MEA75vw==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.972.1.tgz", + "integrity": "sha512-XnNit6H9PPHhqUXW/usjX6JeJ6Pm8ZNqivTjmNjgWHeOfVpblUc/MTic02UmCNR0jJLPjQ3mBKiMen0tnkNQjQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -970,13 +1063,13 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.970.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.970.0.tgz", - "integrity": "sha512-TZNZqFcMUtjvhZoZRtpEGQAdULYiy6rcGiXAbLU7e9LSpIYlRqpLa207oMNfgbzlL2PnHko+eVg8rajDiSOYCg==", + "version": "3.972.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.972.0.tgz", + "integrity": "sha512-6JHsl1V/a1ZW8D8AFfd4R52fwZPnZ5H4U6DS8m/bWT8qad72NvbOFAC7U2cDtFs2TShqUO3TEiX/EJibtY3ijg==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.969.0", + "@aws-sdk/types": "3.972.0", "@smithy/types": "^4.12.0", "@smithy/url-parser": "^4.2.8", "@smithy/util-endpoints": "^3.2.8", @@ -986,10 +1079,24 @@ "node": ">=20.0.0" } }, + "node_modules/@aws-sdk/util-endpoints/node_modules/@aws-sdk/types": { + "version": "3.972.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.972.0.tgz", + "integrity": "sha512-U7xBIbLSetONxb2bNzHyDgND3oKGoIfmknrEVnoEU4GUSs+0augUOIn9DIWGUO2ETcRFdsRUnmx9KhPT9Ojbug==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.12.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.965.2", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.2.tgz", - "integrity": "sha512-qKgO7wAYsXzhwCHhdbaKFyxd83Fgs8/1Ka+jjSPrv2Ll7mB55Wbwlo0kkfMLh993/yEc8aoDIAc1Fz9h4Spi4Q==", + "version": "3.965.3", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.965.3.tgz", + "integrity": "sha512-FNUqAjlKAGA7GM05kywE99q8wiPHPZqrzhq3wXRga6PRD6A0kzT85Pb0AzYBVTBRpSrKyyr6M92Y6bnSBVp2BA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1000,27 +1107,27 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.969.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.969.0.tgz", - "integrity": "sha512-bpJGjuKmFr0rA6UKUCmN8D19HQFMLXMx5hKBXqBlPFdalMhxJSjcxzX9DbQh0Fn6bJtxCguFmRGOBdQqNOt49g==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.972.1.tgz", + "integrity": "sha512-IgF55NFmJX8d9Wql9M0nEpk2eYbuD8G4781FN4/fFgwTXBn86DvlZJuRWDCMcMqZymnBVX7HW9r+3r9ylqfW0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "3.969.0", + "@aws-sdk/types": "^3.973.0", "@smithy/types": "^4.12.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.971.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.971.0.tgz", - "integrity": "sha512-Eygjo9mFzQYjbGY3MYO6CsIhnTwAMd3WmuFalCykqEmj2r5zf0leWrhPaqvA5P68V5JdGfPYgj7vhNOd6CtRBQ==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.972.1.tgz", + "integrity": "sha512-oIs4JFcADzoZ0c915R83XvK2HltWupxNsXUIuZse2rgk7b97zTpkxaqXiH0h9ylh31qtgo/t8hp4tIqcsMrEbQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@aws-sdk/middleware-user-agent": "3.970.0", - "@aws-sdk/types": "3.969.0", + "@aws-sdk/middleware-user-agent": "^3.972.1", + "@aws-sdk/types": "^3.973.0", "@smithy/node-config-provider": "^4.3.8", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" @@ -1038,9 +1145,9 @@ } }, "node_modules/@aws-sdk/xml-builder": { - "version": "3.969.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.969.0.tgz", - "integrity": "sha512-BSe4Lx/qdRQQdX8cSSI7Et20vqBspzAjBy8ZmXVoyLkol3y4sXBXzn+BiLtR+oh60ExQn6o2DU4QjdOZbXaKIQ==", + "version": "3.972.1", + "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.972.1.tgz", + "integrity": "sha512-6zZGlPOqn7Xb+25MAXGb1JhgvaC5HjZj6GzszuVrnEgbhvzBRFGKYemuHBV4bho+dtqeYKPgaZUv7/e80hIGNg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -1811,9 +1918,10 @@ } }, "node_modules/@contentstack/marketplace-sdk": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@contentstack/marketplace-sdk/-/marketplace-sdk-1.4.1.tgz", - "integrity": "sha512-gxklP8+m7Grb4lRudXXNG9BOAiSkTw7Ua8oC9IAAmCfa1BSDMhh7XNphSM5Jj4paH/+1ZQ/StExU7R4MfcIZ1w==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@contentstack/marketplace-sdk/-/marketplace-sdk-1.4.2.tgz", + "integrity": "sha512-eFwSWif5RmHJqniYHNzkC1P0WUN90t1BPfEx8zR9pF0GKETELGVtIwf0tFJ9Ag7zPchQZ63qtcbAQ4WJYWN/+w==", + "hasInstallScript": true, "license": "MIT", "dependencies": { "axios": "^1.13.2" @@ -1912,9 +2020,9 @@ } }, "node_modules/@es-joy/jsdoccomment/node_modules/@typescript-eslint/types": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.0.tgz", - "integrity": "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.1.tgz", + "integrity": "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==", "dev": true, "license": "MIT", "engines": { @@ -3342,6 +3450,27 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "license": "ISC", + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@isaacs/fs-minipass/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -3955,9 +4084,9 @@ } }, "node_modules/@oclif/plugin-help": { - "version": "6.2.36", - "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-6.2.36.tgz", - "integrity": "sha512-NBQIg5hEMhvdbi4mSrdqRGl5XJ0bqTAHq6vDCCCDXUcfVtdk3ZJbSxtRVWyVvo9E28vwqu6MZyHOJylevqcHbA==", + "version": "6.2.37", + "resolved": "https://registry.npmjs.org/@oclif/plugin-help/-/plugin-help-6.2.37.tgz", + "integrity": "sha512-5N/X/FzlJaYfpaHwDC0YHzOzKDWa41s9t+4FpCDu4f9OMReds4JeNBaaWk9rlIzdKjh2M6AC5Q18ORfECRkHGA==", "license": "MIT", "dependencies": { "@oclif/core": "^4" @@ -3967,9 +4096,9 @@ } }, "node_modules/@oclif/plugin-not-found": { - "version": "3.2.73", - "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-3.2.73.tgz", - "integrity": "sha512-2bQieTGI9XNFe9hKmXQjJmHV5rZw+yn7Rud1+C5uLEo8GaT89KZbiLTJgL35tGILahy/cB6+WAs812wjw7TK6w==", + "version": "3.2.74", + "resolved": "https://registry.npmjs.org/@oclif/plugin-not-found/-/plugin-not-found-3.2.74.tgz", + "integrity": "sha512-6RD/EuIUGxAYR45nMQg+nw+PqwCXUxkR6Eyn+1fvbVjtb9d+60OPwB77LCRUI4zKNI+n0LOFaMniEdSpb+A7kQ==", "license": "MIT", "dependencies": { "@inquirer/prompts": "^7.10.1", @@ -3982,9 +4111,9 @@ } }, "node_modules/@oclif/plugin-plugins": { - "version": "5.4.54", - "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-5.4.54.tgz", - "integrity": "sha512-yzdukEfvvyXx31AhN+YhxLhuQdx2SrZDcRtPl5CNkuqh/uNSB2BuA3xpurdv2qotpaw/Z9InRl+Sa9bLp/4aLA==", + "version": "5.4.55", + "resolved": "https://registry.npmjs.org/@oclif/plugin-plugins/-/plugin-plugins-5.4.55.tgz", + "integrity": "sha512-Dmcryvss0CJwaGSVimhIcnWfQto1rAMA5nMN6v6syrOhR76ygw2X7YWvkI6PXCFB/aekT2LJeQHy9Hl/OQJiYQ==", "license": "MIT", "dependencies": { "@oclif/core": "^4.8.0", @@ -4004,9 +4133,9 @@ } }, "node_modules/@oclif/plugin-warn-if-update-available": { - "version": "3.1.54", - "resolved": "https://registry.npmjs.org/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-3.1.54.tgz", - "integrity": "sha512-FrRR1LPTbX3taD4G2AZTZ5TZQIfha73m3c8XyWH5/+QuMo92nLhXWPosr5tJohxU72r+6fut4l0E07lTmX88nA==", + "version": "3.1.55", + "resolved": "https://registry.npmjs.org/@oclif/plugin-warn-if-update-available/-/plugin-warn-if-update-available-3.1.55.tgz", + "integrity": "sha512-VIEBoaoMOCjl3y+w/kdfZMODi0mVMnDuM0vkBf3nqeidhRXVXq87hBqYDdRwN1XoD+eDfE8tBbOP7qtSOONztQ==", "dev": true, "license": "MIT", "dependencies": { @@ -4014,7 +4143,7 @@ "ansis": "^3.17.0", "debug": "^4.4.3", "http-call": "^5.2.2", - "lodash": "^4.17.21", + "lodash": "^4.17.23", "registry-auth-token": "^5.1.1" }, "engines": { @@ -4022,9 +4151,9 @@ } }, "node_modules/@oclif/test": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/@oclif/test/-/test-4.1.15.tgz", - "integrity": "sha512-OVTmz3RxnOWYPoE9sbB9Przfph+QSLMvHUfqEwXZKupuOHCJAJX0QDUfVyh1pK+XYEQ2RUaF+qhxqBfIfaahBw==", + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/@oclif/test/-/test-4.1.16.tgz", + "integrity": "sha512-LPrF++WGGBE0pe3GUkzEteI5WrwTT7usGpIMSxkyJhYnFXKkwASyTcCmOhNH4QC65kqsLt1oBA88BMkCJqPtxg==", "license": "MIT", "dependencies": { "ansis": "^3.17.0", @@ -4262,9 +4391,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.55.1.tgz", - "integrity": "sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.56.0.tgz", + "integrity": "sha512-LNKIPA5k8PF1+jAFomGe3qN3bbIgJe/IlpDBwuVjrDKrJhVWywgnJvflMt/zkbVNLFtF1+94SljYQS6e99klnw==", "cpu": [ "arm" ], @@ -4275,9 +4404,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.55.1.tgz", - "integrity": "sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.56.0.tgz", + "integrity": "sha512-lfbVUbelYqXlYiU/HApNMJzT1E87UPGvzveGg2h0ktUNlOCxKlWuJ9jtfvs1sKHdwU4fzY7Pl8sAl49/XaEk6Q==", "cpu": [ "arm64" ], @@ -4288,9 +4417,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.55.1.tgz", - "integrity": "sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.56.0.tgz", + "integrity": "sha512-EgxD1ocWfhoD6xSOeEEwyE7tDvwTgZc8Bss7wCWe+uc7wO8G34HHCUH+Q6cHqJubxIAnQzAsyUsClt0yFLu06w==", "cpu": [ "arm64" ], @@ -4301,9 +4430,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.55.1.tgz", - "integrity": "sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.56.0.tgz", + "integrity": "sha512-1vXe1vcMOssb/hOF8iv52A7feWW2xnu+c8BV4t1F//m9QVLTfNVpEdja5ia762j/UEJe2Z1jAmEqZAK42tVW3g==", "cpu": [ "x64" ], @@ -4314,9 +4443,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.55.1.tgz", - "integrity": "sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.56.0.tgz", + "integrity": "sha512-bof7fbIlvqsyv/DtaXSck4VYQ9lPtoWNFCB/JY4snlFuJREXfZnm+Ej6yaCHfQvofJDXLDMTVxWscVSuQvVWUQ==", "cpu": [ "arm64" ], @@ -4327,9 +4456,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.55.1.tgz", - "integrity": "sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.56.0.tgz", + "integrity": "sha512-KNa6lYHloW+7lTEkYGa37fpvPq+NKG/EHKM8+G/g9WDU7ls4sMqbVRV78J6LdNuVaeeK5WB9/9VAFbKxcbXKYg==", "cpu": [ "x64" ], @@ -4340,9 +4469,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.55.1.tgz", - "integrity": "sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.56.0.tgz", + "integrity": "sha512-E8jKK87uOvLrrLN28jnAAAChNq5LeCd2mGgZF+fGF5D507WlG/Noct3lP/QzQ6MrqJ5BCKNwI9ipADB6jyiq2A==", "cpu": [ "arm" ], @@ -4353,9 +4482,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.55.1.tgz", - "integrity": "sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.56.0.tgz", + "integrity": "sha512-jQosa5FMYF5Z6prEpTCCmzCXz6eKr/tCBssSmQGEeozA9tkRUty/5Vx06ibaOP9RCrW1Pvb8yp3gvZhHwTDsJw==", "cpu": [ "arm" ], @@ -4366,9 +4495,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.55.1.tgz", - "integrity": "sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.56.0.tgz", + "integrity": "sha512-uQVoKkrC1KGEV6udrdVahASIsaF8h7iLG0U0W+Xn14ucFwi6uS539PsAr24IEF9/FoDtzMeeJXJIBo5RkbNWvQ==", "cpu": [ "arm64" ], @@ -4379,9 +4508,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.55.1.tgz", - "integrity": "sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.56.0.tgz", + "integrity": "sha512-vLZ1yJKLxhQLFKTs42RwTwa6zkGln+bnXc8ueFGMYmBTLfNu58sl5/eXyxRa2RarTkJbXl8TKPgfS6V5ijNqEA==", "cpu": [ "arm64" ], @@ -4392,9 +4521,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.55.1.tgz", - "integrity": "sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.56.0.tgz", + "integrity": "sha512-FWfHOCub564kSE3xJQLLIC/hbKqHSVxy8vY75/YHHzWvbJL7aYJkdgwD/xGfUlL5UV2SB7otapLrcCj2xnF1dg==", "cpu": [ "loong64" ], @@ -4405,9 +4534,9 @@ ] }, "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.55.1.tgz", - "integrity": "sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.56.0.tgz", + "integrity": "sha512-z1EkujxIh7nbrKL1lmIpqFTc/sr0u8Uk0zK/qIEFldbt6EDKWFk/pxFq3gYj4Bjn3aa9eEhYRlL3H8ZbPT1xvA==", "cpu": [ "loong64" ], @@ -4418,9 +4547,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.55.1.tgz", - "integrity": "sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.56.0.tgz", + "integrity": "sha512-iNFTluqgdoQC7AIE8Q34R3AuPrJGJirj5wMUErxj22deOcY7XwZRaqYmB6ZKFHoVGqRcRd0mqO+845jAibKCkw==", "cpu": [ "ppc64" ], @@ -4431,9 +4560,9 @@ ] }, "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.55.1.tgz", - "integrity": "sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.56.0.tgz", + "integrity": "sha512-MtMeFVlD2LIKjp2sE2xM2slq3Zxf9zwVuw0jemsxvh1QOpHSsSzfNOTH9uYW9i1MXFxUSMmLpeVeUzoNOKBaWg==", "cpu": [ "ppc64" ], @@ -4444,9 +4573,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.55.1.tgz", - "integrity": "sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.56.0.tgz", + "integrity": "sha512-in+v6wiHdzzVhYKXIk5U74dEZHdKN9KH0Q4ANHOTvyXPG41bajYRsy7a8TPKbYPl34hU7PP7hMVHRvv/5aCSew==", "cpu": [ "riscv64" ], @@ -4457,9 +4586,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.55.1.tgz", - "integrity": "sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.56.0.tgz", + "integrity": "sha512-yni2raKHB8m9NQpI9fPVwN754mn6dHQSbDTwxdr9SE0ks38DTjLMMBjrwvB5+mXrX+C0npX0CVeCUcvvvD8CNQ==", "cpu": [ "riscv64" ], @@ -4470,9 +4599,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.55.1.tgz", - "integrity": "sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.56.0.tgz", + "integrity": "sha512-zhLLJx9nQPu7wezbxt2ut+CI4YlXi68ndEve16tPc/iwoylWS9B3FxpLS2PkmfYgDQtosah07Mj9E0khc3Y+vQ==", "cpu": [ "s390x" ], @@ -4483,9 +4612,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.55.1.tgz", - "integrity": "sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.56.0.tgz", + "integrity": "sha512-MVC6UDp16ZSH7x4rtuJPAEoE1RwS8N4oK9DLHy3FTEdFoUTCFVzMfJl/BVJ330C+hx8FfprA5Wqx4FhZXkj2Kw==", "cpu": [ "x64" ], @@ -4496,9 +4625,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.55.1.tgz", - "integrity": "sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.56.0.tgz", + "integrity": "sha512-ZhGH1eA4Qv0lxaV00azCIS1ChedK0V32952Md3FtnxSqZTBTd6tgil4nZT5cU8B+SIw3PFYkvyR4FKo2oyZIHA==", "cpu": [ "x64" ], @@ -4509,9 +4638,9 @@ ] }, "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.55.1.tgz", - "integrity": "sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.56.0.tgz", + "integrity": "sha512-O16XcmyDeFI9879pEcmtWvD/2nyxR9mF7Gs44lf1vGGx8Vg2DRNx11aVXBEqOQhWb92WN4z7fW/q4+2NYzCbBA==", "cpu": [ "x64" ], @@ -4522,9 +4651,9 @@ ] }, "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.55.1.tgz", - "integrity": "sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.56.0.tgz", + "integrity": "sha512-LhN/Reh+7F3RCgQIRbgw8ZMwUwyqJM+8pXNT6IIJAqm2IdKkzpCh/V9EdgOMBKuebIrzswqy4ATlrDgiOwbRcQ==", "cpu": [ "arm64" ], @@ -4535,9 +4664,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.55.1.tgz", - "integrity": "sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.56.0.tgz", + "integrity": "sha512-kbFsOObXp3LBULg1d3JIUQMa9Kv4UitDmpS+k0tinPBz3watcUiV2/LUDMMucA6pZO3WGE27P7DsfaN54l9ing==", "cpu": [ "arm64" ], @@ -4548,9 +4677,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.55.1.tgz", - "integrity": "sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.56.0.tgz", + "integrity": "sha512-vSSgny54D6P4vf2izbtFm/TcWYedw7f8eBrOiGGecyHyQB9q4Kqentjaj8hToe+995nob/Wv48pDqL5a62EWtg==", "cpu": [ "ia32" ], @@ -4561,9 +4690,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.55.1.tgz", - "integrity": "sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.56.0.tgz", + "integrity": "sha512-FeCnkPCTHQJFbiGG49KjV5YGW/8b9rrXAM2Mz2kiIoktq2qsJxRD5giEMEOD2lPdgs72upzefaUvS+nc8E3UzQ==", "cpu": [ "x64" ], @@ -4574,9 +4703,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.55.1.tgz", - "integrity": "sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.56.0.tgz", + "integrity": "sha512-H8AE9Ur/t0+1VXujj90w0HrSOuv0Nq9r1vSZF2t5km20NTfosQsGGUXDaKdQZzwuLts7IyL1fYT4hM95TI9c4g==", "cpu": [ "x64" ], @@ -4741,9 +4870,9 @@ } }, "node_modules/@smithy/core": { - "version": "3.20.7", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.20.7.tgz", - "integrity": "sha512-aO7jmh3CtrmPsIJxUwYIzI5WVlMK8BMCPQ4D4nTzqTqBhbzvxHNzBMGcEg13yg/z9R2Qsz49NUFl0F0lVbTVFw==", + "version": "3.21.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.21.1.tgz", + "integrity": "sha512-NUH8R4O6FkN8HKMojzbGg/5pNjsfTjlMmeFclyPfPaXXUrbr5TzhWgbf7t92wfrpCHRgpjyz7ffASIS3wX28aA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -4976,13 +5105,13 @@ } }, "node_modules/@smithy/middleware-endpoint": { - "version": "4.4.8", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.8.tgz", - "integrity": "sha512-TV44qwB/T0OMMzjIuI+JeS0ort3bvlPJ8XIH0MSlGADraXpZqmyND27ueuAL3E14optleADWqtd7dUgc2w+qhQ==", + "version": "4.4.11", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.11.tgz", + "integrity": "sha512-/WqsrycweGGfb9sSzME4CrsuayjJF6BueBmkKlcbeU5q18OhxRrvvKlmfw3tpDsK5ilx2XUJvoukwxHB0nHs/Q==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.20.7", + "@smithy/core": "^3.21.1", "@smithy/middleware-serde": "^4.2.9", "@smithy/node-config-provider": "^4.3.8", "@smithy/shared-ini-file-loader": "^4.4.3", @@ -4996,16 +5125,16 @@ } }, "node_modules/@smithy/middleware-retry": { - "version": "4.4.24", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.24.tgz", - "integrity": "sha512-yiUY1UvnbUFfP5izoKLtfxDSTRv724YRRwyiC/5HYY6vdsVDcDOXKSXmkJl/Hovcxt5r+8tZEUAdrOaCJwrl9Q==", + "version": "4.4.27", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.27.tgz", + "integrity": "sha512-xFUYCGRVsfgiN5EjsJJSzih9+yjStgMTCLANPlf0LVQkPDYCe0hz97qbdTZosFOiYlGBlHYityGRxrQ/hxhfVQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/node-config-provider": "^4.3.8", "@smithy/protocol-http": "^5.3.8", "@smithy/service-error-classification": "^4.2.8", - "@smithy/smithy-client": "^4.10.9", + "@smithy/smithy-client": "^4.10.12", "@smithy/types": "^4.12.0", "@smithy/util-middleware": "^4.2.8", "@smithy/util-retry": "^4.2.8", @@ -5183,14 +5312,14 @@ } }, "node_modules/@smithy/smithy-client": { - "version": "4.10.9", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.10.9.tgz", - "integrity": "sha512-Je0EvGXVJ0Vrrr2lsubq43JGRIluJ/hX17aN/W/A0WfE+JpoMdI8kwk2t9F0zTX9232sJDGcoH4zZre6m6f/sg==", + "version": "4.10.12", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.10.12.tgz", + "integrity": "sha512-VKO/HKoQ5OrSHW6AJUmEnUKeXI1/5LfCwO9cwyao7CmLvGnZeM1i36Lyful3LK1XU7HwTVieTqO1y2C/6t3qtA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@smithy/core": "^3.20.7", - "@smithy/middleware-endpoint": "^4.4.8", + "@smithy/core": "^3.21.1", + "@smithy/middleware-endpoint": "^4.4.11", "@smithy/middleware-stack": "^4.2.8", "@smithy/protocol-http": "^5.3.8", "@smithy/types": "^4.12.0", @@ -5298,14 +5427,14 @@ } }, "node_modules/@smithy/util-defaults-mode-browser": { - "version": "4.3.23", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.23.tgz", - "integrity": "sha512-mMg+r/qDfjfF/0psMbV4zd7F/i+rpyp7Hjh0Wry7eY15UnzTEId+xmQTGDU8IdZtDfbGQxuWNfgBZKBj+WuYbA==", + "version": "4.3.26", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.26.tgz", + "integrity": "sha512-vva0dzYUTgn7DdE0uaha10uEdAgmdLnNFowKFjpMm6p2R0XDk5FHPX3CBJLzWQkQXuEprsb0hGz9YwbicNWhjw==", "dev": true, "license": "Apache-2.0", "dependencies": { "@smithy/property-provider": "^4.2.8", - "@smithy/smithy-client": "^4.10.9", + "@smithy/smithy-client": "^4.10.12", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, @@ -5314,9 +5443,9 @@ } }, "node_modules/@smithy/util-defaults-mode-node": { - "version": "4.2.26", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.26.tgz", - "integrity": "sha512-EQqe/WkbCinah0h1lMWh9ICl0Ob4lyl20/10WTB35SC9vDQfD8zWsOT+x2FIOXKAoZQ8z/y0EFMoodbcqWJY/w==", + "version": "4.2.29", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.29.tgz", + "integrity": "sha512-c6D7IUBsZt/aNnTBHMTf+OVh+h/JcxUUgfTcIJaWRe6zhOum1X+pNKSZtZ+7fbOn5I99XVFtmrnXKv8yHHErTQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -5324,7 +5453,7 @@ "@smithy/credential-provider-imds": "^4.2.8", "@smithy/node-config-provider": "^4.3.8", "@smithy/property-provider": "^4.2.8", - "@smithy/smithy-client": "^4.10.9", + "@smithy/smithy-client": "^4.10.12", "@smithy/types": "^4.12.0", "tslib": "^2.6.2" }, @@ -5495,14 +5624,14 @@ } }, "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.0.tgz", - "integrity": "sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.1.tgz", + "integrity": "sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0" + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5513,9 +5642,9 @@ } }, "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.0.tgz", - "integrity": "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.1.tgz", + "integrity": "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==", "dev": true, "license": "MIT", "engines": { @@ -5527,16 +5656,16 @@ } }, "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.0.tgz", - "integrity": "sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.1.tgz", + "integrity": "sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.53.0", - "@typescript-eslint/tsconfig-utils": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0", + "@typescript-eslint/project-service": "8.53.1", + "@typescript-eslint/tsconfig-utils": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", @@ -5555,16 +5684,16 @@ } }, "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.0.tgz", - "integrity": "sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.1.tgz", + "integrity": "sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0" + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -5579,13 +5708,13 @@ } }, "node_modules/@stylistic/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.0.tgz", - "integrity": "sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.1.tgz", + "integrity": "sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", + "@typescript-eslint/types": "8.53.1", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -6249,14 +6378,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.53.0.tgz", - "integrity": "sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.53.1.tgz", + "integrity": "sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.53.0", - "@typescript-eslint/types": "^8.53.0", + "@typescript-eslint/tsconfig-utils": "^8.53.1", + "@typescript-eslint/types": "^8.53.1", "debug": "^4.4.3" }, "engines": { @@ -6271,9 +6400,9 @@ } }, "node_modules/@typescript-eslint/project-service/node_modules/@typescript-eslint/types": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.0.tgz", - "integrity": "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.1.tgz", + "integrity": "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==", "dev": true, "license": "MIT", "engines": { @@ -6303,9 +6432,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.0.tgz", - "integrity": "sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.53.1.tgz", + "integrity": "sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==", "dev": true, "license": "MIT", "engines": { @@ -7472,9 +7601,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.9.15", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.15.tgz", - "integrity": "sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==", + "version": "2.9.17", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.17.tgz", + "integrity": "sha512-agD0MgJFUP/4nvjqzIB29zRPUuCF7Ge6mEv9s8dHrtYD7QWXRcx75rOADE/d5ah1NI+0vkDl0yorDd5U852IQQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -7957,9 +8086,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001765", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001765.tgz", - "integrity": "sha512-LWcNtSyZrakjECqmpP4qdg0MMGdN368D7X8XvvAqOcqMv0RxnlqVKZl2V6/mBR68oYMxOZPLw/gO7DuisMHUvQ==", + "version": "1.0.30001766", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001766.tgz", + "integrity": "sha512-4C0lfJ0/YPjJQHagaE9x2Elb69CIqEPZeG0anQt9SIvIoOH4a4uaRl73IavyO+0qZh6MDLH//DrXThEYKHkmYA==", "dev": true, "funding": [ { @@ -8151,12 +8280,12 @@ } }, "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "license": "BlueOak-1.0.0", "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/ci-info": { @@ -8777,13 +8906,13 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.47.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", - "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", + "version": "3.48.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz", + "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.28.0" + "browserslist": "^4.28.1" }, "funding": { "type": "opencollective", @@ -9236,9 +9365,9 @@ } }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz", + "integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -9396,9 +9525,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.267", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", - "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "version": "1.5.277", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.277.tgz", + "integrity": "sha512-wKXFZw4erWmmOz5N/grBoJ2XrNJGDFMu2+W5ACHza5rHtvsqrK4gb6rnLC7XxKB9WlJ+RmyQatuEXmtm86xbnw==", "dev": true, "license": "ISC" }, @@ -9813,9 +9942,9 @@ } }, "node_modules/eslint-config-oclif": { - "version": "6.0.132", - "resolved": "https://registry.npmjs.org/eslint-config-oclif/-/eslint-config-oclif-6.0.132.tgz", - "integrity": "sha512-vvO4HiZxQvG896XjZA0QW5LRd+eJvO3bNR8WPSQwbzqBUhCn0pzd8wUuz609fQnbBg4E1qnemGRe49/NRx3KJA==", + "version": "6.0.133", + "resolved": "https://registry.npmjs.org/eslint-config-oclif/-/eslint-config-oclif-6.0.133.tgz", + "integrity": "sha512-cCa/K8JwanplkBku4wiRuWAZ4VF6z0V23Y0wC5Sjdf2x7ZJsZ5vqg6/OJqKELXc/0TzfoLX56luHS/IIeYdnag==", "dev": true, "license": "MIT", "dependencies": { @@ -10266,17 +10395,17 @@ } }, "node_modules/eslint-config-oclif/node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.0.tgz", - "integrity": "sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.1.tgz", + "integrity": "sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.53.0", - "@typescript-eslint/type-utils": "8.53.0", - "@typescript-eslint/utils": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0", + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/type-utils": "8.53.1", + "@typescript-eslint/utils": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" @@ -10289,7 +10418,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.53.0", + "@typescript-eslint/parser": "^8.53.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } @@ -10305,16 +10434,16 @@ } }, "node_modules/eslint-config-oclif/node_modules/@typescript-eslint/parser": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.0.tgz", - "integrity": "sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.1.tgz", + "integrity": "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0", + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3" }, "engines": { @@ -10330,14 +10459,14 @@ } }, "node_modules/eslint-config-oclif/node_modules/@typescript-eslint/scope-manager": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.0.tgz", - "integrity": "sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.1.tgz", + "integrity": "sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0" + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10348,15 +10477,15 @@ } }, "node_modules/eslint-config-oclif/node_modules/@typescript-eslint/type-utils": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.0.tgz", - "integrity": "sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.1.tgz", + "integrity": "sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0", - "@typescript-eslint/utils": "8.53.0", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1", + "@typescript-eslint/utils": "8.53.1", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, @@ -10373,9 +10502,9 @@ } }, "node_modules/eslint-config-oclif/node_modules/@typescript-eslint/types": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.0.tgz", - "integrity": "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.1.tgz", + "integrity": "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==", "dev": true, "license": "MIT", "engines": { @@ -10387,16 +10516,16 @@ } }, "node_modules/eslint-config-oclif/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.0.tgz", - "integrity": "sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.1.tgz", + "integrity": "sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.53.0", - "@typescript-eslint/tsconfig-utils": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0", + "@typescript-eslint/project-service": "8.53.1", + "@typescript-eslint/tsconfig-utils": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", @@ -10431,16 +10560,16 @@ } }, "node_modules/eslint-config-oclif/node_modules/@typescript-eslint/utils": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.0.tgz", - "integrity": "sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.1.tgz", + "integrity": "sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0" + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -10455,13 +10584,13 @@ } }, "node_modules/eslint-config-oclif/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.0.tgz", - "integrity": "sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.1.tgz", + "integrity": "sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", + "@typescript-eslint/types": "8.53.1", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -10699,9 +10828,9 @@ } }, "node_modules/eslint-config-oclif/node_modules/eslint-config-xo/node_modules/espree": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-11.0.0.tgz", - "integrity": "sha512-+gMeWRrIh/NsG+3NaLeWHuyeyk70p2tbvZIWBYcqQ4/7Xvars6GYTZNhF1sIeLcc6Wb11He5ffz3hsHyXFrw5A==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.1.0.tgz", + "integrity": "sha512-WFWYhO1fV4iYkqOOvq8FbqIhr2pYfoDY0kCotMkDeNtGpiGGkZ1iov2u8ydjtgM8yF8rzK7oaTbw2NAzbAbehw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -11266,14 +11395,14 @@ } }, "node_modules/eslint-plugin-perfectionist/node_modules/@typescript-eslint/scope-manager": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.0.tgz", - "integrity": "sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.1.tgz", + "integrity": "sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0" + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11284,9 +11413,9 @@ } }, "node_modules/eslint-plugin-perfectionist/node_modules/@typescript-eslint/types": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.0.tgz", - "integrity": "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.1.tgz", + "integrity": "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==", "dev": true, "license": "MIT", "engines": { @@ -11298,16 +11427,16 @@ } }, "node_modules/eslint-plugin-perfectionist/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.0.tgz", - "integrity": "sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.1.tgz", + "integrity": "sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.53.0", - "@typescript-eslint/tsconfig-utils": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0", + "@typescript-eslint/project-service": "8.53.1", + "@typescript-eslint/tsconfig-utils": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", @@ -11326,16 +11455,16 @@ } }, "node_modules/eslint-plugin-perfectionist/node_modules/@typescript-eslint/utils": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.0.tgz", - "integrity": "sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.1.tgz", + "integrity": "sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0" + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -11350,13 +11479,13 @@ } }, "node_modules/eslint-plugin-perfectionist/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.0.tgz", - "integrity": "sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.1.tgz", + "integrity": "sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", + "@typescript-eslint/types": "8.53.1", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -12475,36 +12604,6 @@ "node": ">=14.14" } }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs-minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/fs-then-native": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", @@ -16568,9 +16667,9 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", "license": "MIT" }, "node_modules/lodash.camelcase": { @@ -17239,36 +17338,26 @@ } }, "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", "license": "MIT", "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" + "minipass": "^7.1.2" }, "engines": { - "node": ">= 8" + "node": ">= 18" } }, "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/mixme": { "version": "0.5.10", "resolved": "https://registry.npmjs.org/mixme/-/mixme-0.5.10.tgz", @@ -20599,9 +20688,9 @@ } }, "node_modules/oclif": { - "version": "4.22.67", - "resolved": "https://registry.npmjs.org/oclif/-/oclif-4.22.67.tgz", - "integrity": "sha512-7r5jNcJRvrlnHmIlXIHoiUILKtxxrcDXkdYGXseexjJrJsywdTjhDspx0D/IshJ9cZyKHF9J3mxpILjvZ/7a3g==", + "version": "4.22.68", + "resolved": "https://registry.npmjs.org/oclif/-/oclif-4.22.68.tgz", + "integrity": "sha512-XYAhVTgnomHmvaOe1upNI8rTV4dNmkCF4T9onhVVUiEF4Z8M8rNJXuW8Ba5+BFLyfRIL+Rp/sFZU6EYWbZ7DEg==", "dev": true, "license": "MIT", "dependencies": { @@ -20623,7 +20712,7 @@ "fs-extra": "^8.1", "github-slugger": "^2", "got": "^13", - "lodash": "^4.17.21", + "lodash": "^4.17.23", "normalize-package-data": "^6", "semver": "^7.7.3", "sort-package-json": "^2.15.1", @@ -23021,9 +23110,9 @@ } }, "node_modules/rollup": { - "version": "4.55.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.55.1.tgz", - "integrity": "sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==", + "version": "4.56.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.56.0.tgz", + "integrity": "sha512-9FwVqlgUHzbXtDg9RCMgodF3Ua4Na6Gau+Sdt9vyCN4RhHfVKX2DCHy3BjMLTDd47ITDhYAnTwGulWTblJSDLg==", "license": "MIT", "dependencies": { "@types/estree": "1.0.8" @@ -23036,31 +23125,31 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.55.1", - "@rollup/rollup-android-arm64": "4.55.1", - "@rollup/rollup-darwin-arm64": "4.55.1", - "@rollup/rollup-darwin-x64": "4.55.1", - "@rollup/rollup-freebsd-arm64": "4.55.1", - "@rollup/rollup-freebsd-x64": "4.55.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.55.1", - "@rollup/rollup-linux-arm-musleabihf": "4.55.1", - "@rollup/rollup-linux-arm64-gnu": "4.55.1", - "@rollup/rollup-linux-arm64-musl": "4.55.1", - "@rollup/rollup-linux-loong64-gnu": "4.55.1", - "@rollup/rollup-linux-loong64-musl": "4.55.1", - "@rollup/rollup-linux-ppc64-gnu": "4.55.1", - "@rollup/rollup-linux-ppc64-musl": "4.55.1", - "@rollup/rollup-linux-riscv64-gnu": "4.55.1", - "@rollup/rollup-linux-riscv64-musl": "4.55.1", - "@rollup/rollup-linux-s390x-gnu": "4.55.1", - "@rollup/rollup-linux-x64-gnu": "4.55.1", - "@rollup/rollup-linux-x64-musl": "4.55.1", - "@rollup/rollup-openbsd-x64": "4.55.1", - "@rollup/rollup-openharmony-arm64": "4.55.1", - "@rollup/rollup-win32-arm64-msvc": "4.55.1", - "@rollup/rollup-win32-ia32-msvc": "4.55.1", - "@rollup/rollup-win32-x64-gnu": "4.55.1", - "@rollup/rollup-win32-x64-msvc": "4.55.1", + "@rollup/rollup-android-arm-eabi": "4.56.0", + "@rollup/rollup-android-arm64": "4.56.0", + "@rollup/rollup-darwin-arm64": "4.56.0", + "@rollup/rollup-darwin-x64": "4.56.0", + "@rollup/rollup-freebsd-arm64": "4.56.0", + "@rollup/rollup-freebsd-x64": "4.56.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.56.0", + "@rollup/rollup-linux-arm-musleabihf": "4.56.0", + "@rollup/rollup-linux-arm64-gnu": "4.56.0", + "@rollup/rollup-linux-arm64-musl": "4.56.0", + "@rollup/rollup-linux-loong64-gnu": "4.56.0", + "@rollup/rollup-linux-loong64-musl": "4.56.0", + "@rollup/rollup-linux-ppc64-gnu": "4.56.0", + "@rollup/rollup-linux-ppc64-musl": "4.56.0", + "@rollup/rollup-linux-riscv64-gnu": "4.56.0", + "@rollup/rollup-linux-riscv64-musl": "4.56.0", + "@rollup/rollup-linux-s390x-gnu": "4.56.0", + "@rollup/rollup-linux-x64-gnu": "4.56.0", + "@rollup/rollup-linux-x64-musl": "4.56.0", + "@rollup/rollup-openbsd-x64": "4.56.0", + "@rollup/rollup-openharmony-arm64": "4.56.0", + "@rollup/rollup-win32-arm64-msvc": "4.56.0", + "@rollup/rollup-win32-ia32-msvc": "4.56.0", + "@rollup/rollup-win32-x64-gnu": "4.56.0", + "@rollup/rollup-win32-x64-msvc": "4.56.0", "fsevents": "~2.3.2" } }, @@ -24636,37 +24725,38 @@ } }, "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me", - "license": "ISC", + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.6.tgz", + "integrity": "sha512-xqUeu2JAIJpXyvskvU3uvQW8PAmHrtXp2KDuMJwQqW8Sqq0CaZBAQ+dKS3RBXVhU4wC5NjAdKrmh84241gO9cA==", + "license": "BlueOak-1.0.0", "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" }, "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "license": "ISC", "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=18" + } }, "node_modules/temp-path": { "version": "1.0.0", @@ -25040,9 +25130,9 @@ } }, "node_modules/ts-node/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -25351,16 +25441,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.53.0.tgz", - "integrity": "sha512-xHURCQNxZ1dsWn0sdOaOfCSQG0HKeqSj9OexIxrz6ypU6wHYOdX2I3D2b8s8wFSsSOYJb+6q283cLiLlkEsBYw==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.53.1.tgz", + "integrity": "sha512-gB+EVQfP5RDElh9ittfXlhZJdjSU4jUSTyE2+ia8CYyNvet4ElfaLlAIqDvQV9JPknKx0jQH1racTYe/4LaLSg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.53.0", - "@typescript-eslint/parser": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0", - "@typescript-eslint/utils": "8.53.0" + "@typescript-eslint/eslint-plugin": "8.53.1", + "@typescript-eslint/parser": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1", + "@typescript-eslint/utils": "8.53.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -25375,17 +25465,17 @@ } }, "node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.0.tgz", - "integrity": "sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.53.1.tgz", + "integrity": "sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.53.0", - "@typescript-eslint/type-utils": "8.53.0", - "@typescript-eslint/utils": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0", + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/type-utils": "8.53.1", + "@typescript-eslint/utils": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" @@ -25398,22 +25488,22 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.53.0", + "@typescript-eslint/parser": "^8.53.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.0.tgz", - "integrity": "sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.53.1.tgz", + "integrity": "sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0", + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3" }, "engines": { @@ -25429,14 +25519,14 @@ } }, "node_modules/typescript-eslint/node_modules/@typescript-eslint/scope-manager": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.0.tgz", - "integrity": "sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.53.1.tgz", + "integrity": "sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0" + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -25447,15 +25537,15 @@ } }, "node_modules/typescript-eslint/node_modules/@typescript-eslint/type-utils": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.0.tgz", - "integrity": "sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.53.1.tgz", + "integrity": "sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0", - "@typescript-eslint/utils": "8.53.0", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1", + "@typescript-eslint/utils": "8.53.1", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, @@ -25472,9 +25562,9 @@ } }, "node_modules/typescript-eslint/node_modules/@typescript-eslint/types": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.0.tgz", - "integrity": "sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.53.1.tgz", + "integrity": "sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==", "dev": true, "license": "MIT", "engines": { @@ -25486,16 +25576,16 @@ } }, "node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.0.tgz", - "integrity": "sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.53.1.tgz", + "integrity": "sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.53.0", - "@typescript-eslint/tsconfig-utils": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/visitor-keys": "8.53.0", + "@typescript-eslint/project-service": "8.53.1", + "@typescript-eslint/tsconfig-utils": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/visitor-keys": "8.53.1", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", @@ -25514,16 +25604,16 @@ } }, "node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.0.tgz", - "integrity": "sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.53.1.tgz", + "integrity": "sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.53.0", - "@typescript-eslint/types": "8.53.0", - "@typescript-eslint/typescript-estree": "8.53.0" + "@typescript-eslint/scope-manager": "8.53.1", + "@typescript-eslint/types": "8.53.1", + "@typescript-eslint/typescript-estree": "8.53.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -25538,13 +25628,13 @@ } }, "node_modules/typescript-eslint/node_modules/@typescript-eslint/visitor-keys": { - "version": "8.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.0.tgz", - "integrity": "sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==", + "version": "8.53.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.53.1.tgz", + "integrity": "sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.53.0", + "@typescript-eslint/types": "8.53.1", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -26378,26 +26468,26 @@ }, "packages/contentstack": { "name": "@contentstack/cli", - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.5", "license": "MIT", "dependencies": { "@contentstack/cli-audit": "~2.0.0-beta.1", "@contentstack/cli-auth": "~2.0.0-beta.1", - "@contentstack/cli-cm-bootstrap": "~2.0.0-beta.3", + "@contentstack/cli-cm-bootstrap": "~2.0.0-beta.4", "@contentstack/cli-cm-branches": "~1.6.1", "@contentstack/cli-cm-bulk-publish": "~1.10.3", - "@contentstack/cli-cm-clone": "~2.0.0-beta.4", - "@contentstack/cli-cm-export": "~2.0.0-beta.4", + "@contentstack/cli-cm-clone": "~2.0.0-beta.5", + "@contentstack/cli-cm-export": "~2.0.0-beta.5", "@contentstack/cli-cm-export-to-csv": "~1.10.1", - "@contentstack/cli-cm-import": "~2.0.0-beta.3", + "@contentstack/cli-cm-import": "~2.0.0-beta.4", "@contentstack/cli-cm-import-setup": "~2.0.0-beta.2", - "@contentstack/cli-cm-seed": "~2.0.0-beta.3", + "@contentstack/cli-cm-seed": "~2.0.0-beta.4", "@contentstack/cli-command": "~1.7.0", "@contentstack/cli-config": "~1.16.1", "@contentstack/cli-launch": "1.9.3", "@contentstack/cli-migration": "~2.0.0-beta.1", "@contentstack/cli-utilities": "~1.15.0", - "@contentstack/cli-variants": "~2.0.0-beta.3", + "@contentstack/cli-variants": "~2.0.0-beta.4", "@contentstack/management": "~1.22.0", "@oclif/core": "^4.3.0", "@oclif/plugin-help": "^6.2.28", @@ -26687,17 +26777,17 @@ }, "packages/contentstack-bootstrap": { "name": "@contentstack/cli-cm-bootstrap", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "license": "MIT", "dependencies": { - "@contentstack/cli-cm-seed": "~2.0.0-beta.3", + "@contentstack/cli-cm-seed": "~2.0.0-beta.4", "@contentstack/cli-command": "~1.7.0", "@contentstack/cli-utilities": "~1.15.0", "@oclif/core": "^4.3.0", "@oclif/plugin-help": "^6.2.28", "inquirer": "8.2.7", "mkdirp": "^1.0.4", - "tar": "^6.2.1 " + "tar": "^7.5.4 " }, "devDependencies": { "@oclif/test": "^4.1.13", @@ -26728,9 +26818,9 @@ "license": "MIT" }, "packages/contentstack-bootstrap/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -26886,12 +26976,12 @@ }, "packages/contentstack-clone": { "name": "@contentstack/cli-cm-clone", - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.5", "license": "MIT", "dependencies": { "@colors/colors": "^1.6.0", - "@contentstack/cli-cm-export": "~2.0.0-beta.4", - "@contentstack/cli-cm-import": "~2.0.0-beta.3", + "@contentstack/cli-cm-export": "~2.0.0-beta.5", + "@contentstack/cli-cm-import": "~2.0.0-beta.4", "@contentstack/cli-command": "~1.7.0", "@contentstack/cli-utilities": "~1.15.0", "@oclif/core": "^4.3.0", @@ -27080,9 +27170,9 @@ "license": "MIT" }, "packages/contentstack-command/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -27514,13 +27604,13 @@ }, "packages/contentstack-export": { "name": "@contentstack/cli-cm-export", - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.5", "license": "MIT", "dependencies": { - "@contentstack/cli-command": "~1.7.0", + "@contentstack/cli-command": "~1.7.1", "@contentstack/cli-utilities": "~1.15.0", - "@contentstack/cli-variants": "~2.0.0-beta.3", - "@oclif/core": "^4.3.3", + "@contentstack/cli-variants": "~2.0.0-beta.4", + "@oclif/core": "^4.8.0", "async": "^3.2.6", "big-json": "^3.2.0", "bluebird": "^3.7.2", @@ -27908,13 +27998,13 @@ } }, "packages/contentstack-export/node_modules/@contentstack/cli-auth/node_modules/@contentstack/cli-utilities": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@contentstack/cli-utilities/-/cli-utilities-1.16.0.tgz", - "integrity": "sha512-2SlKE9bJH3bd+ESNq1c9FWRCYzIjuWxRtXp+83eX7qDzHA7Lgu2EsRjfq+TcYVtBdCd0BzVATRIU2t/vNUl5Zw==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@contentstack/cli-utilities/-/cli-utilities-1.16.1.tgz", + "integrity": "sha512-aQ+P/+mUDAE1qpY/7XuX3bb+KLXJZpDxj5gsmco4InJyxojR7rLKwwYVvD8f/MLSw5x3kkkwytpXmHFeTAFA6w==", "dev": true, "license": "MIT", "dependencies": { - "@contentstack/management": "~1.25.1", + "@contentstack/management": "~1.27.3", "@contentstack/marketplace-sdk": "^1.4.0", "@oclif/core": "^4.3.0", "axios": "^1.9.0", @@ -27961,12 +28051,12 @@ } }, "packages/contentstack-export/node_modules/@contentstack/cli-command/node_modules/@contentstack/cli-utilities": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/@contentstack/cli-utilities/-/cli-utilities-1.16.0.tgz", - "integrity": "sha512-2SlKE9bJH3bd+ESNq1c9FWRCYzIjuWxRtXp+83eX7qDzHA7Lgu2EsRjfq+TcYVtBdCd0BzVATRIU2t/vNUl5Zw==", + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/@contentstack/cli-utilities/-/cli-utilities-1.16.1.tgz", + "integrity": "sha512-aQ+P/+mUDAE1qpY/7XuX3bb+KLXJZpDxj5gsmco4InJyxojR7rLKwwYVvD8f/MLSw5x3kkkwytpXmHFeTAFA6w==", "license": "MIT", "dependencies": { - "@contentstack/management": "~1.25.1", + "@contentstack/management": "~1.27.3", "@contentstack/marketplace-sdk": "^1.4.0", "@oclif/core": "^4.3.0", "axios": "^1.9.0", @@ -28031,19 +28121,20 @@ } }, "packages/contentstack-export/node_modules/@contentstack/management": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/@contentstack/management/-/management-1.25.1.tgz", - "integrity": "sha512-454V3zGw4nrxnlYxXm82Z+yNjuechiN+TRE7SXWyHFUsexYVpKNyGyKZCvG6b4JymRTVUZpy/KnFixo01GP9Sg==", + "version": "1.27.3", + "resolved": "https://registry.npmjs.org/@contentstack/management/-/management-1.27.3.tgz", + "integrity": "sha512-6gL2MgKDnPdIOeqgYjLibhzzuXj9uRyLrIuN00XdpfXiJE6mQ343GwQ7EOMzXcMf17/sedDJ7C7BKLSdDtG2Zg==", "license": "MIT", "dependencies": { + "@contentstack/utils": "^1.6.3", "assert": "^2.1.0", "axios": "^1.12.2", "buffer": "^6.0.3", - "form-data": "^4.0.4", + "form-data": "^4.0.5", "husky": "^9.1.7", "lodash": "^4.17.21", "otplib": "^12.0.1", - "qs": "^6.14.0", + "qs": "6.14.1", "stream-browserify": "^3.0.0" }, "engines": { @@ -28199,14 +28290,14 @@ }, "packages/contentstack-import": { "name": "@contentstack/cli-cm-import", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "license": "MIT", "dependencies": { "@contentstack/cli-audit": "~2.0.0-beta.1", "@contentstack/cli-command": "~1.7.0", "@contentstack/cli-utilities": "~1.15.0", - "@contentstack/cli-variants": "~2.0.0-beta.3", - "@contentstack/management": "~1.22.0", + "@contentstack/cli-variants": "~2.0.0-beta.4", + "@contentstack/management": "~1.27.2", "@oclif/core": "^4.3.0", "big-json": "^3.2.0", "bluebird": "^3.7.2", @@ -28334,6 +28425,27 @@ "node": ">=4.2.0" } }, + "packages/contentstack-import/node_modules/@contentstack/management": { + "version": "1.27.3", + "resolved": "https://registry.npmjs.org/@contentstack/management/-/management-1.27.3.tgz", + "integrity": "sha512-6gL2MgKDnPdIOeqgYjLibhzzuXj9uRyLrIuN00XdpfXiJE6mQ343GwQ7EOMzXcMf17/sedDJ7C7BKLSdDtG2Zg==", + "license": "MIT", + "dependencies": { + "@contentstack/utils": "^1.6.3", + "assert": "^2.1.0", + "axios": "^1.12.2", + "buffer": "^6.0.3", + "form-data": "^4.0.5", + "husky": "^9.1.7", + "lodash": "^4.17.21", + "otplib": "^12.0.1", + "qs": "6.14.1", + "stream-browserify": "^3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, "packages/contentstack-import/node_modules/@types/mocha": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-8.2.3.tgz", @@ -28413,16 +28525,16 @@ }, "packages/contentstack-seed": { "name": "@contentstack/cli-cm-seed", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "license": "MIT", "dependencies": { - "@contentstack/cli-cm-import": "~2.0.0-beta.3", + "@contentstack/cli-cm-import": "~2.0.0-beta.4", "@contentstack/cli-command": "~1.7.0", "@contentstack/cli-utilities": "~1.15.0", "@contentstack/management": "~1.22.0", "inquirer": "8.2.7", "mkdirp": "^1.0.4", - "tar": "^6.2.1", + "tar": "^7.5.4", "tmp": "^0.2.3" }, "devDependencies": { @@ -28454,9 +28566,9 @@ "license": "MIT" }, "packages/contentstack-seed/node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -28661,7 +28773,7 @@ }, "packages/contentstack-variants": { "name": "@contentstack/cli-variants", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "license": "MIT", "dependencies": { "@contentstack/cli-utilities": "~1.15.0", diff --git a/packages/contentstack-bootstrap/README.md b/packages/contentstack-bootstrap/README.md index 3e453feef3..6904b8aaa7 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/2.0.0-beta.3 darwin-arm64 node-v24.12.0 +@contentstack/cli-cm-bootstrap/2.0.0-beta.4 darwin-arm64 node-v24.12.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-bootstrap/package.json b/packages/contentstack-bootstrap/package.json index 0b5b87a36b..0281a72420 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": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "author": "Contentstack", "bugs": "https://github.com/contentstack/cli/issues", "scripts": { @@ -16,14 +16,14 @@ "test:report": "nyc --reporter=lcov mocha \"test/**/*.test.js\"" }, "dependencies": { - "@contentstack/cli-cm-seed": "~2.0.0-beta.3", + "@contentstack/cli-cm-seed": "~2.0.0-beta.4", "@contentstack/cli-command": "~1.7.0", "@contentstack/cli-utilities": "~1.15.0", "@oclif/core": "^4.3.0", "@oclif/plugin-help": "^6.2.28", "inquirer": "8.2.7", "mkdirp": "^1.0.4", - "tar": "^6.2.1 " + "tar": "^7.5.4 " }, "devDependencies": { "@oclif/test": "^4.1.13", @@ -72,4 +72,4 @@ } }, "repository": "contentstack/cli" -} +} \ No newline at end of file diff --git a/packages/contentstack-clone/README.md b/packages/contentstack-clone/README.md index be37e47a3c..3fc4705cce 100644 --- a/packages/contentstack-clone/README.md +++ b/packages/contentstack-clone/README.md @@ -16,7 +16,7 @@ $ npm install -g @contentstack/cli-cm-clone $ csdx COMMAND running command... $ csdx (--version) -@contentstack/cli-cm-clone/2.0.0-beta.4 darwin-arm64 node-v24.12.0 +@contentstack/cli-cm-clone/2.0.0-beta.5 darwin-arm64 node-v24.12.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-clone/package.json b/packages/contentstack-clone/package.json index 160ad9488c..0d6dde427c 100644 --- a/packages/contentstack-clone/package.json +++ b/packages/contentstack-clone/package.json @@ -1,13 +1,13 @@ { "name": "@contentstack/cli-cm-clone", "description": "Contentstack stack clone plugin", - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.5", "author": "Contentstack", "bugs": "https://github.com/rohitmishra209/cli-cm-clone/issues", "dependencies": { "@colors/colors": "^1.6.0", - "@contentstack/cli-cm-export": "~2.0.0-beta.4", - "@contentstack/cli-cm-import": "~2.0.0-beta.3", + "@contentstack/cli-cm-export": "~2.0.0-beta.5", + "@contentstack/cli-cm-import": "~2.0.0-beta.4", "@contentstack/cli-command": "~1.7.0", "@contentstack/cli-utilities": "~1.15.0", "@oclif/core": "^4.3.0", @@ -64,4 +64,4 @@ "cm:stacks:clone": "CLN" } } -} +} \ No newline at end of file diff --git a/packages/contentstack-clone/src/lib/util/clone-handler.js b/packages/contentstack-clone/src/lib/util/clone-handler.js index 0bd4aab725..c9d4f0448f 100644 --- a/packages/contentstack-clone/src/lib/util/clone-handler.js +++ b/packages/contentstack-clone/src/lib/util/clone-handler.js @@ -76,7 +76,6 @@ class CloneHandler { cloneCommand = new Clone(); this.pathDir = opt.pathDir; process.stdin.setMaxListeners(50); - log.debug('Initializing CloneHandler', config.cloneContext, { pathDir: opt.pathDir, cloneType: opt.cloneType }); } setClient(managementSDKClient) { client = managementSDKClient; @@ -706,9 +705,14 @@ class CloneHandler { delete exportConfig.import; delete exportConfig.export; + // Map source_stack to apiKey for export config + if (exportConfig.source_stack) { + exportConfig.apiKey = exportConfig.source_stack; + } + const exportDir = __dirname.split('src')[0] + 'contents'; log.debug(`Export directory: ${exportDir}`, config.cloneContext); - const cmd = ['-k', exportConfig.source_stack, '-d', exportDir]; + const cmd = ['-k', exportConfig.apiKey || exportConfig.source_stack, '-d', exportDir]; if (exportConfig.cloneType === 'a') { exportConfig.filteredModules = ['stack'].concat(structureList); @@ -738,7 +742,7 @@ class CloneHandler { log.debug('Export command prepared', config.cloneContext, { cmd: cmd.join(' '), exportDir, - sourceStack: exportConfig.source_stack, + sourceStack: exportConfig.apiKey || exportConfig.source_stack, branch: exportConfig.sourceStackBranch }); log.debug('Running export command', config.cloneContext, { cmd }); @@ -760,6 +764,14 @@ class CloneHandler { delete importConfig.import; delete importConfig.export; + // Map target_stack to apiKey and data to contentDir for import config + if (importConfig.target_stack) { + importConfig.apiKey = importConfig.target_stack; + } + if (importConfig.data) { + importConfig.contentDir = importConfig.data; + } + const configFilePath = path.join(__dirname, 'dummyConfig.json'); const cmd = ['-c', configFilePath]; @@ -767,7 +779,7 @@ class CloneHandler { cmd.push('-a', importConfig.destination_alias); log.debug(`Using destination alias: ${importConfig.destination_alias}`, config.cloneContext); } - if (!importConfig.data && importConfig.sourceStackBranch) { + if (!importConfig.contentDir && !importConfig.data && importConfig.sourceStackBranch) { const dataPath = path.join(importConfig.pathDir, importConfig.sourceStackBranch); cmd.push('-d', dataPath); log.debug(`Import data path: ${dataPath}`, config.cloneContext); @@ -795,9 +807,9 @@ class CloneHandler { fs.writeFileSync(configFilePath, JSON.stringify(importConfig)); log.debug('Import command prepared', config.cloneContext, { cmd: cmd.join(' '), - targetStack: importConfig.target_stack, + targetStack: importConfig.apiKey || importConfig.target_stack, targetBranch: importConfig.targetStackBranch, - dataPath: importConfig.data || path.join(importConfig.pathDir, importConfig.sourceStackBranch) + dataPath: importConfig.contentDir || importConfig.data || path.join(importConfig.pathDir, importConfig.sourceStackBranch) }); log.debug('Running import command', config.cloneContext, { cmd }); await importCmd.run(cmd); diff --git a/packages/contentstack-export-to-csv/package.json b/packages/contentstack-export-to-csv/package.json index 2b8c1b560d..3599956e90 100644 --- a/packages/contentstack-export-to-csv/package.json +++ b/packages/contentstack-export-to-csv/package.json @@ -65,4 +65,4 @@ } }, "repository": "https://github.com/contentstack/cli" -} +} \ No newline at end of file diff --git a/packages/contentstack-export/README.md b/packages/contentstack-export/README.md index f843741978..628d41b040 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/2.0.0-beta.4 darwin-arm64 node-v24.12.0 +@contentstack/cli-cm-export/2.0.0-beta.5 darwin-arm64 node-v24.12.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-export/example_config/auth_config.json b/packages/contentstack-export/example_config/auth_config.json index 47043d7bb3..0b7a88155e 100644 --- a/packages/contentstack-export/example_config/auth_config.json +++ b/packages/contentstack-export/example_config/auth_config.json @@ -1,5 +1,4 @@ { - "contentVersion": 2, "master_locale": { "name": "English - United States", "code": "en-us" diff --git a/packages/contentstack-export/example_config/management_config.json b/packages/contentstack-export/example_config/management_config.json index bbd71c6efd..5767b2f7ee 100644 --- a/packages/contentstack-export/example_config/management_config.json +++ b/packages/contentstack-export/example_config/management_config.json @@ -1,5 +1,4 @@ { - "contentVersion": 2, "master_locale": { "name": "English - United States", "code": "en-us" diff --git a/packages/contentstack-export/package.json b/packages/contentstack-export/package.json index 57c8f047fb..5ab0cd3c78 100644 --- a/packages/contentstack-export/package.json +++ b/packages/contentstack-export/package.json @@ -1,14 +1,14 @@ { "name": "@contentstack/cli-cm-export", "description": "Contentstack CLI plugin to export content from stack", - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.5", "author": "Contentstack", "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { - "@contentstack/cli-command": "~1.7.0", - "@oclif/core": "^4.3.3", - "@contentstack/cli-variants": "~2.0.0-beta.3", + "@contentstack/cli-command": "~1.7.1", "@contentstack/cli-utilities": "~1.15.0", + "@contentstack/cli-variants": "~2.0.0-beta.4", + "@oclif/core": "^4.8.0", "async": "^3.2.6", "big-json": "^3.2.0", "bluebird": "^3.7.2", @@ -94,4 +94,4 @@ } }, "repository": "https://github.com/contentstack/cli" -} +} \ No newline at end of file diff --git a/packages/contentstack-export/src/commands/cm/stacks/export.ts b/packages/contentstack-export/src/commands/cm/stacks/export.ts index 479cbe1d1f..82b2ca94a5 100644 --- a/packages/contentstack-export/src/commands/cm/stacks/export.ts +++ b/packages/contentstack-export/src/commands/cm/stacks/export.ts @@ -98,7 +98,7 @@ export default class ExportCommand extends Command { // Assign exportConfig variables this.assignExportConfig(exportConfig); - exportDir = sanitizePath(exportConfig.cliLogsPath || exportConfig.data || exportConfig.exportDir); + exportDir = sanitizePath(exportConfig.cliLogsPath || exportConfig.exportDir); const managementAPIClient: ContentstackClient = await managementSDKClient(exportConfig); const moduleExporter = new ModuleExporter(managementAPIClient, exportConfig); await moduleExporter.start(); diff --git a/packages/contentstack-export/src/export/modules/assets.ts b/packages/contentstack-export/src/export/modules/assets.ts index f774f2c6eb..efd8542ea2 100644 --- a/packages/contentstack-export/src/export/modules/assets.ts +++ b/packages/contentstack-export/src/export/modules/assets.ts @@ -47,8 +47,8 @@ export default class ExportAssets extends BaseClass { } async start(): Promise { - this.assetsRootPath = pResolve( - this.exportConfig.data, + this.assetsRootPath = pResolve( + this.exportConfig.exportDir, this.exportConfig.branchName || '', this.assetConfig.dirName, ); diff --git a/packages/contentstack-export/src/export/modules/composable-studio.ts b/packages/contentstack-export/src/export/modules/composable-studio.ts index 8faff8c2b5..265248d129 100644 --- a/packages/contentstack-export/src/export/modules/composable-studio.ts +++ b/packages/contentstack-export/src/export/modules/composable-studio.ts @@ -41,7 +41,7 @@ export default class ExportComposableStudio { } this.composableStudioPath = pResolve( - this.exportConfig.data, + this.exportConfig.exportDir, this.exportConfig.branchName || '', this.composableStudioConfig.dirName, ); diff --git a/packages/contentstack-export/src/export/modules/content-types.ts b/packages/contentstack-export/src/export/modules/content-types.ts index c69baf707d..c1d6f72355 100644 --- a/packages/contentstack-export/src/export/modules/content-types.ts +++ b/packages/contentstack-export/src/export/modules/content-types.ts @@ -47,7 +47,7 @@ export default class ContentTypesExport extends BaseClass { this.applyQueryFilters(this.qs, 'content-types'); this.contentTypesDirPath = path.resolve( - sanitizePath(exportConfig.data), + sanitizePath(exportConfig.exportDir), sanitizePath(exportConfig.branchName || ''), sanitizePath(this.contentTypesConfig.dirName), ); diff --git a/packages/contentstack-export/src/export/modules/custom-roles.ts b/packages/contentstack-export/src/export/modules/custom-roles.ts index 48bb96fdcc..0c6f6aec7b 100644 --- a/packages/contentstack-export/src/export/modules/custom-roles.ts +++ b/packages/contentstack-export/src/export/modules/custom-roles.ts @@ -43,7 +43,7 @@ export default class ExportCustomRoles extends BaseClass { 'CUSTOM-ROLES: Analyzing roles and locales...', async () => { this.rolesFolderPath = pResolve( - this.exportConfig.data, + this.exportConfig.exportDir, this.exportConfig.branchName || '', this.customRolesConfig.dirName, ); diff --git a/packages/contentstack-export/src/export/modules/entries.ts b/packages/contentstack-export/src/export/modules/entries.ts index e4187af9ba..eccc40c40f 100644 --- a/packages/contentstack-export/src/export/modules/entries.ts +++ b/packages/contentstack-export/src/export/modules/entries.ts @@ -41,18 +41,18 @@ export default class EntriesExport extends BaseClass { this.exportConfig = exportConfig; this.entriesConfig = exportConfig.modules.entries; this.entriesDirPath = path.resolve( - sanitizePath(exportConfig.data), + sanitizePath(exportConfig.exportDir), sanitizePath(exportConfig.branchName || ''), sanitizePath(this.entriesConfig.dirName), ); this.localesFilePath = path.resolve( - sanitizePath(exportConfig.data), + sanitizePath(exportConfig.exportDir), sanitizePath(exportConfig.branchName || ''), sanitizePath(exportConfig.modules.locales.dirName), sanitizePath(exportConfig.modules.locales.fileName), ); this.schemaFilePath = path.resolve( - sanitizePath(exportConfig.data), + sanitizePath(exportConfig.exportDir), sanitizePath(exportConfig.branchName || ''), sanitizePath(exportConfig.modules.content_types.dirName), 'schema.json', diff --git a/packages/contentstack-export/src/export/modules/environments.ts b/packages/contentstack-export/src/export/modules/environments.ts index 68961f3e17..31173b0319 100644 --- a/packages/contentstack-export/src/export/modules/environments.ts +++ b/packages/contentstack-export/src/export/modules/environments.ts @@ -32,7 +32,7 @@ export default class ExportEnvironments extends BaseClass { // Setup with loading spinner const [totalCount] = await this.withLoadingSpinner('ENVIRONMENTS: Analyzing environments...', async () => { this.environmentsFolderPath = pResolve( - this.exportConfig.data, + this.exportConfig.exportDir, this.exportConfig.branchName || '', this.environmentConfig.dirName, ); diff --git a/packages/contentstack-export/src/export/modules/extensions.ts b/packages/contentstack-export/src/export/modules/extensions.ts index 7665aa30c9..dcadf5df89 100644 --- a/packages/contentstack-export/src/export/modules/extensions.ts +++ b/packages/contentstack-export/src/export/modules/extensions.ts @@ -33,7 +33,7 @@ export default class ExportExtensions extends BaseClass { // Setup with loading spinner const [totalCount] = await this.withLoadingSpinner('EXTENSIONS: Analyzing extensions...', async () => { this.extensionsFolderPath = pResolve( - this.exportConfig.data, + this.exportConfig.exportDir, this.exportConfig.branchName || '', this.extensionConfig.dirName, ); diff --git a/packages/contentstack-export/src/export/modules/global-fields.ts b/packages/contentstack-export/src/export/modules/global-fields.ts index c89ef88264..4159ae5333 100644 --- a/packages/contentstack-export/src/export/modules/global-fields.ts +++ b/packages/contentstack-export/src/export/modules/global-fields.ts @@ -38,7 +38,7 @@ export default class GlobalFieldsExport extends BaseClass { include_global_field_schema: true, }; this.globalFieldsDirPath = path.resolve( - sanitizePath(exportConfig.data), + sanitizePath(exportConfig.exportDir), sanitizePath(exportConfig.branchName || ''), sanitizePath(this.globalFieldsConfig.dirName), ); diff --git a/packages/contentstack-export/src/export/modules/labels.ts b/packages/contentstack-export/src/export/modules/labels.ts index aa9edab2bf..dab2625903 100644 --- a/packages/contentstack-export/src/export/modules/labels.ts +++ b/packages/contentstack-export/src/export/modules/labels.ts @@ -32,7 +32,7 @@ export default class ExportLabels extends BaseClass { // Setup with loading spinner const [totalCount] = await this.withLoadingSpinner('LABELS: Analyzing labels...', async () => { this.labelsFolderPath = pResolve( - this.exportConfig.data, + this.exportConfig.exportDir, this.exportConfig.branchName || '', this.labelConfig.dirName, ); diff --git a/packages/contentstack-export/src/export/modules/locales.ts b/packages/contentstack-export/src/export/modules/locales.ts index 58cc3960ee..2919983c6f 100644 --- a/packages/contentstack-export/src/export/modules/locales.ts +++ b/packages/contentstack-export/src/export/modules/locales.ts @@ -42,7 +42,7 @@ export default class LocaleExport extends BaseClass { }, }; this.localesPath = path.resolve( - sanitizePath(exportConfig.data), + sanitizePath(exportConfig.exportDir), sanitizePath(exportConfig.branchName || ''), sanitizePath(this.localeConfig.dirName), ); diff --git a/packages/contentstack-export/src/export/modules/marketplace-apps.ts b/packages/contentstack-export/src/export/modules/marketplace-apps.ts index 49e4a9872f..a258f5bc68 100644 --- a/packages/contentstack-export/src/export/modules/marketplace-apps.ts +++ b/packages/contentstack-export/src/export/modules/marketplace-apps.ts @@ -121,7 +121,7 @@ export default class ExportMarketplaceApps extends BaseClass { async setupPaths(): Promise { this.marketplaceAppPath = pResolve( - this.exportConfig.data, + this.exportConfig.exportDir, this.exportConfig.branchName || '', this.marketplaceAppConfig.dirName, ); @@ -133,7 +133,7 @@ export default class ExportMarketplaceApps extends BaseClass { this.developerHubBaseUrl = this.exportConfig.developerHubBaseUrl || (await getDeveloperHubUrl(this.exportConfig)); log.debug(`Developer hub base URL: '${this.developerHubBaseUrl}'`, this.exportConfig.context); this.exportConfig.org_uid = await getOrgUid(this.exportConfig); - this.query = { target_uids: this.exportConfig.source_stack }; + this.query = { target_uids: this.exportConfig.apiKey }; log.debug(`Organization UID: '${this.exportConfig.org_uid}'.`, this.exportConfig.context); // NOTE init marketplace app sdk diff --git a/packages/contentstack-export/src/export/modules/stack.ts b/packages/contentstack-export/src/export/modules/stack.ts index 47af303ba0..8077682a59 100644 --- a/packages/contentstack-export/src/export/modules/stack.ts +++ b/packages/contentstack-export/src/export/modules/stack.ts @@ -25,7 +25,7 @@ export default class ExportStack extends BaseClass { this.stackConfig = exportConfig.modules.stack; this.qs = { include_count: true }; this.stackFolderPath = pResolve( - this.exportConfig.data, + this.exportConfig.exportDir, this.exportConfig.branchName || '', this.stackConfig.dirName, ); @@ -130,20 +130,20 @@ export default class ExportStack extends BaseClass { } async getStack(): Promise { - log.debug(`Fetching stack data for: '${this.exportConfig.source_stack}'...`, this.exportConfig.context); + log.debug(`Fetching stack data for: '${this.exportConfig.apiKey}'...`, this.exportConfig.context); const tempAPIClient = await managementSDKClient({ host: this.exportConfig.host }); log.debug(`Created Management SDK client with host: '${this.exportConfig.host}'.`, this.exportConfig.context); return await tempAPIClient - .stack({ api_key: this.exportConfig.source_stack }) + .stack({ api_key: this.exportConfig.apiKey }) .fetch() .then((data: any) => { - log.debug(`Successfully fetched stack data for: '${this.exportConfig.source_stack}'.`, this.exportConfig.context); + log.debug(`Successfully fetched stack data for: '${this.exportConfig.apiKey}'.`, this.exportConfig.context); return data; }) .catch((error: any) => { - log.debug(`Failed to fetch stack data for: '${this.exportConfig.source_stack}'.`, this.exportConfig.context); + log.debug(`Failed to fetch stack data for: '${this.exportConfig.apiKey}'.`, this.exportConfig.context); return {}; }); } @@ -183,7 +183,7 @@ export default class ExportStack extends BaseClass { return masterLocalObj; } else if (skip >= count) { log.error( - `Locale locale not found in the stack ${this.exportConfig.source_stack}. Please ensure that the stack has a master locale.`, + `Locale locale not found in the stack ${this.exportConfig.apiKey}. Please ensure that the stack has a master locale.`, this.exportConfig.context, ); log.debug('Completed search. Master locale not found.', this.exportConfig.context); @@ -201,7 +201,7 @@ export default class ExportStack extends BaseClass { }) .catch((error: any) => { log.debug( - `Error occurred while fetching locales for stack: ${this.exportConfig.source_stack}`, + `Error occurred while fetching locales for stack: ${this.exportConfig.apiKey}`, this.exportConfig.context, ); this.progressManager?.tick( @@ -213,14 +213,14 @@ export default class ExportStack extends BaseClass { handleAndLogError( error, { ...this.exportConfig.context }, - `Failed to fetch locales for stack ${this.exportConfig.source_stack}`, + `Failed to fetch locales for stack ${this.exportConfig.apiKey}`, ); throw error; }); } async exportStack(): Promise { - log.debug(`Starting stack export for: '${this.exportConfig.source_stack}'...`, this.exportConfig.context); + log.debug(`Starting stack export for: '${this.exportConfig.apiKey}'...`, this.exportConfig.context); await fsUtil.makeDirectory(this.stackFolderPath); log.debug(`Created stack directory at: '${this.stackFolderPath}'`, this.exportConfig.context); @@ -235,20 +235,20 @@ export default class ExportStack extends BaseClass { // Track progress for stack export completion this.progressManager?.tick( true, - `stack: ${this.exportConfig.source_stack}`, + `stack: ${this.exportConfig.apiKey}`, null, PROCESS_NAMES.STACK_DETAILS, ); log.success( - `Stack details exported successfully for stack ${this.exportConfig.source_stack}`, + `Stack details exported successfully for stack ${this.exportConfig.apiKey}`, this.exportConfig.context, ); log.debug('Stack export completed successfully.', this.exportConfig.context); return resp; }) .catch((error: any) => { - log.debug(`Error occurred while exporting stack: ${this.exportConfig.source_stack}`, this.exportConfig.context); + log.debug(`Error occurred while exporting stack: ${this.exportConfig.apiKey}`, this.exportConfig.context); this.progressManager?.tick( false, 'stack export', diff --git a/packages/contentstack-export/src/export/modules/taxonomies.ts b/packages/contentstack-export/src/export/modules/taxonomies.ts index 136abb311f..2f9fa502c6 100644 --- a/packages/contentstack-export/src/export/modules/taxonomies.ts +++ b/packages/contentstack-export/src/export/modules/taxonomies.ts @@ -42,7 +42,7 @@ export default class ExportTaxonomies extends BaseClass { this.applyQueryFilters(this.qs, 'taxonomies'); this.exportConfig.context.module = 'taxonomies'; this.localesFilePath = pResolve( - sanitizePath(exportConfig.data), + sanitizePath(exportConfig.exportDir), sanitizePath(exportConfig.branchName || ''), sanitizePath(exportConfig.modules.locales.dirName), sanitizePath(exportConfig.modules.locales.fileName), @@ -54,7 +54,7 @@ export default class ExportTaxonomies extends BaseClass { //create taxonomies folder this.taxonomiesFolderPath = pResolve( - this.exportConfig.data, + this.exportConfig.exportDir, this.exportConfig.branchName || '', this.taxonomiesConfig.dirName, ); diff --git a/packages/contentstack-export/src/export/modules/webhooks.ts b/packages/contentstack-export/src/export/modules/webhooks.ts index 26f3d40232..a0bec4fd88 100644 --- a/packages/contentstack-export/src/export/modules/webhooks.ts +++ b/packages/contentstack-export/src/export/modules/webhooks.ts @@ -33,7 +33,7 @@ export default class ExportWebhooks extends BaseClass { // Setup with loading spinner const [totalCount] = await this.withLoadingSpinner('WEBHOOKS: Analyzing webhooks...', async () => { this.webhooksFolderPath = pResolve( - this.exportConfig.data, + this.exportConfig.exportDir, this.exportConfig.branchName || '', this.webhookConfig.dirName, ); diff --git a/packages/contentstack-export/src/export/modules/workflows.ts b/packages/contentstack-export/src/export/modules/workflows.ts index 6fcb9db356..e0ae4192b5 100644 --- a/packages/contentstack-export/src/export/modules/workflows.ts +++ b/packages/contentstack-export/src/export/modules/workflows.ts @@ -32,7 +32,7 @@ export default class ExportWorkFlows extends BaseClass { // Setup with loading spinner const [totalCount] = await this.withLoadingSpinner('WORKFLOWS: Analyzing workflows...', async () => { this.webhooksFolderPath = pResolve( - this.exportConfig.data, + this.exportConfig.exportDir, this.exportConfig.branchName || '', this.workflowConfig.dirName, ); diff --git a/packages/contentstack-export/src/utils/basic-login.ts b/packages/contentstack-export/src/utils/basic-login.ts index 650c12d40c..3f2b5226e8 100644 --- a/packages/contentstack-export/src/utils/basic-login.ts +++ b/packages/contentstack-export/src/utils/basic-login.ts @@ -16,7 +16,7 @@ const login = async (config: ExternalConfig): Promise => { const response = await client.login({ email: config.email, password: config.password }).catch(Promise.reject); if (response?.user?.authtoken) { config.headers = { - api_key: config.source_stack, + api_key: config.apiKey, access_token: config.access_token, authtoken: response.user.authtoken, 'X-User-Agent': 'contentstack-export/v', @@ -28,7 +28,7 @@ const login = async (config: ExternalConfig): Promise => { log.error(`Failed to log in!`, config.context); process.exit(1); } - } else if (!config.email && !config.password && config.source_stack && config.access_token) { + } else if (!config.email && !config.password && config.apiKey && config.access_token) { log.info( `Content types, entries, assets, labels, global fields, extensions modules will be exported`, config.context, @@ -38,7 +38,7 @@ const login = async (config: ExternalConfig): Promise => { config.context, ); config.headers = { - api_key: config.source_stack, + api_key: config.apiKey, access_token: config.access_token, 'X-User-Agent': 'contentstack-export/v', }; diff --git a/packages/contentstack-export/src/utils/common-helper.ts b/packages/contentstack-export/src/utils/common-helper.ts index 8721244370..f6fd972a38 100644 --- a/packages/contentstack-export/src/utils/common-helper.ts +++ b/packages/contentstack-export/src/utils/common-helper.ts @@ -15,13 +15,13 @@ export const validateConfig = function (config: ExternalConfig) { throw new Error('Host/CDN end point is missing from config'); } - if (config.email && config.password && !config.access_token && !config.source_stack) { + if (config.email && config.password && !config.access_token && !config.apiKey) { throw new Error('Kindly provide access_token or api_token'); } else if ( !config.email && !config.password && !config.management_token && - config.source_stack && + config.apiKey && !config.access_token && !isAuthenticated() ) { @@ -30,7 +30,7 @@ export const validateConfig = function (config: ExternalConfig) { config.email && config.password && !config.access_token && - config.source_stack && + config.apiKey && !config.management_token && !isAuthenticated() ) { diff --git a/packages/contentstack-export/src/utils/export-config-handler.ts b/packages/contentstack-export/src/utils/export-config-handler.ts index cbacd7e115..dbccfb84c3 100644 --- a/packages/contentstack-export/src/utils/export-config-handler.ts +++ b/packages/contentstack-export/src/utils/export-config-handler.ts @@ -12,7 +12,7 @@ const setupConfig = async (exportCmdFlags: any): Promise => { // Set progress supported module FIRST, before any log calls // This ensures the logger respects the showConsoleLogs setting correctly configHandler.set('log.progressSupportedModule', 'export'); - + let config = merge({}, defaultConfig); // Track authentication method @@ -24,10 +24,12 @@ const setupConfig = async (exportCmdFlags: any): Promise => { if (exportCmdFlags['config']) { log.debug('Loading external configuration file...', { configFile: exportCmdFlags['config'] }); const externalConfig = await readFile(exportCmdFlags['config']); + + config = merge.recursive(config, externalConfig); } config.exportDir = sanitizePath( - exportCmdFlags['data'] || exportCmdFlags['data-dir'] || config.data || (await askExportDir()), + exportCmdFlags['data'] || exportCmdFlags['data-dir'] || config.exportDir || (await askExportDir()), ); const pattern = /[*$%#<>{}!&?]/g; @@ -40,9 +42,6 @@ const setupConfig = async (exportCmdFlags: any): Promise => { config.exportDir = config.exportDir.replace(/['"]/g, ''); config.exportDir = path.resolve(config.exportDir); - //Note to support the old key - config.data = config.exportDir; - const managementTokenAlias = exportCmdFlags['management-token-alias'] || exportCmdFlags['alias']; if (managementTokenAlias) { @@ -84,7 +83,7 @@ const setupConfig = async (exportCmdFlags: any): Promise => { } config.apiKey = - exportCmdFlags['stack-uid'] || exportCmdFlags['stack-api-key'] || config.source_stack || (await askAPIKey()); + exportCmdFlags['stack-uid'] || exportCmdFlags['stack-api-key'] || config.apiKey || (await askAPIKey()); if (typeof config.apiKey !== 'string') { log.debug('Invalid API key received!', { apiKey: config.apiKey }); throw new Error('Invalid API key received'); @@ -92,16 +91,13 @@ const setupConfig = async (exportCmdFlags: any): Promise => { } } - // Note support old config - config.source_stack = config.apiKey; - config.forceStopMarketplaceAppsPrompt = exportCmdFlags.yes; config.auth_token = configHandler.get('authtoken'); // TBD handle auth token in httpClient & sdk config.isAuthenticated = isAuthenticated(); if (exportCmdFlags['branch-alias']) { config.branchAlias = exportCmdFlags['branch-alias']; - } + } if (exportCmdFlags['branch']) { config.branchName = exportCmdFlags['branch']; } diff --git a/packages/contentstack-export/src/utils/logger.ts b/packages/contentstack-export/src/utils/logger.ts index ba3122d66a..5169715774 100644 --- a/packages/contentstack-export/src/utils/logger.ts +++ b/packages/contentstack-export/src/utils/logger.ts @@ -137,7 +137,7 @@ function init(_logPath: string) { } export const log = async (config: ExportConfig, message: any, type: string) => { - const logsPath = sanitizePath(config.cliLogsPath || config.data); + const logsPath = sanitizePath(config.cliLogsPath || config.exportDir); // ignoring the type argument, as we are not using it to create a logfile anymore if (type !== 'error') { // removed type argument from init method diff --git a/packages/contentstack-export/src/utils/marketplace-app-helper.ts b/packages/contentstack-export/src/utils/marketplace-app-helper.ts index 18f2eea49b..a88fdb674d 100644 --- a/packages/contentstack-export/src/utils/marketplace-app-helper.ts +++ b/packages/contentstack-export/src/utils/marketplace-app-helper.ts @@ -15,7 +15,7 @@ export const getDeveloperHubUrl = async (exportConfig: ExportConfig) => { export async function getOrgUid(config: ExportConfig): Promise { const tempAPIClient = await managementSDKClient({ host: config.host }); const tempStackData = await tempAPIClient - .stack({ api_key: config.source_stack }) + .stack({ api_key: config.apiKey }) .fetch() .catch((error: any) => { handleAndLogError(error, { ...config.context }); diff --git a/packages/contentstack-export/test/unit/export/modules/assets.test.ts b/packages/contentstack-export/test/unit/export/modules/assets.test.ts index 1a58409517..6c0071ffed 100644 --- a/packages/contentstack-export/test/unit/export/modules/assets.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/assets.test.ts @@ -15,14 +15,13 @@ describe('ExportAssets', () => { asset: sinon.stub().returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: mockData.findData.items }), - count: sinon.stub().resolves(mockData.countData) + count: sinon.stub().resolves(mockData.countData), }), - download: sinon.stub().resolves({ data: 'stream-data' }) - }) + download: sinon.stub().resolves({ data: 'stream-data' }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -37,7 +36,7 @@ describe('ExportAssets', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -46,7 +45,7 @@ describe('ExportAssets', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -63,7 +62,7 @@ describe('ExportAssets', () => { users: '', extension: '', webhooks: '', - stacks: '' + stacks: '', }, preserveStackVersion: false, personalizationEnabled: false, @@ -71,57 +70,56 @@ describe('ExportAssets', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['assets'], locales: { dirName: 'locales', fileName: 'locales.json', - requiredKeys: ['code'] + requiredKeys: ['code'], }, customRoles: { dirName: 'custom_roles', fileName: 'custom_roles.json', - customRolesLocalesFileName: '' + customRolesLocalesFileName: '', }, 'custom-roles': { dirName: 'custom_roles', fileName: 'custom_roles.json', - customRolesLocalesFileName: '' + customRolesLocalesFileName: '', }, environments: { dirName: 'environments', - fileName: 'environments.json' + fileName: 'environments.json', }, labels: { dirName: 'labels', fileName: 'labels.json', - invalidKeys: [] + invalidKeys: [], }, webhooks: { dirName: 'webhooks', - fileName: 'webhooks.json' + fileName: 'webhooks.json', }, releases: { dirName: 'releases', fileName: 'releases.json', releasesList: 'releases_list.json', - invalidKeys: [] + invalidKeys: [], }, workflows: { dirName: 'workflows', fileName: 'workflows.json', - invalidKeys: [] + invalidKeys: [], }, globalfields: { dirName: 'global_fields', fileName: 'globalfields.json', - validKeys: ['title', 'uid'] + validKeys: ['title', 'uid'], }, 'global-fields': { dirName: 'global_fields', fileName: 'globalfields.json', - validKeys: ['title', 'uid'] + validKeys: ['title', 'uid'], }, assets: { dirName: 'assets', @@ -136,19 +134,19 @@ describe('ExportAssets', () => { securedAssets: false, displayExecutionTime: false, enableDownloadStatus: false, - includeVersionedAssets: false + includeVersionedAssets: false, }, content_types: { dirName: 'content_types', fileName: 'content_types.json', validKeys: ['title', 'uid'], - limit: 100 + limit: 100, }, 'content-types': { dirName: 'content_types', fileName: 'content_types.json', validKeys: ['title', 'uid'], - limit: 100 + limit: 100, }, entries: { dirName: 'entries', @@ -157,76 +155,76 @@ describe('ExportAssets', () => { batchLimit: 100, downloadLimit: 5, limit: 100, - exportVersions: false + exportVersions: false, }, personalize: { dirName: 'personalize', - baseURL: {} + baseURL: {}, }, variantEntry: { dirName: 'variant_entries', fileName: 'variant_entries.json', chunkFileSize: 5, - query: { skip: 0, limit: 100, include_variant: true, include_count: false, include_publish_details: true } + query: { skip: 0, limit: 100, include_variant: true, include_count: false, include_publish_details: true }, }, extensions: { dirName: 'extensions', - fileName: 'extensions.json' + fileName: 'extensions.json', }, stack: { dirName: 'stack', - fileName: 'stack.json' + fileName: 'stack.json', }, dependency: { - entries: [] + entries: [], }, marketplace_apps: { dirName: 'marketplace_apps', - fileName: 'marketplace_apps.json' + fileName: 'marketplace_apps.json', }, 'marketplace-apps': { dirName: 'marketplace_apps', - fileName: 'marketplace_apps.json' + fileName: 'marketplace_apps.json', }, 'composable-studio': { dirName: 'composable-studio', fileName: 'composable-studio.json', apiBaseUrl: 'https://api.contentstack.io', - apiVersion: 'v1' + apiVersion: 'v1', }, masterLocale: { dirName: 'master_locale', fileName: 'master_locale.json', - requiredKeys: ['code'] + requiredKeys: ['code'], }, taxonomies: { dirName: 'taxonomies', fileName: 'taxonomies.json', invalidKeys: [], - limit: 100 + limit: 100, }, events: { dirName: 'events', fileName: 'events.json', - invalidKeys: [] + invalidKeys: [], }, audiences: { dirName: 'audiences', fileName: 'audiences.json', - invalidKeys: [] + invalidKeys: [], }, attributes: { dirName: 'attributes', fileName: 'attributes.json', - invalidKeys: [] - } - } + invalidKeys: [], + }, + }, } as ExportConfig; exportAssets = new ExportAssets({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'assets' + moduleName: 'assets', }); }); @@ -285,22 +283,22 @@ describe('ExportAssets', () => { getAssetsCountStub.callsFake((isFolder?: boolean) => { return Promise.resolve(isFolder ? 5 : 10); }); - + // Ensure stubs return resolved promises getAssetsFoldersStub.resolves(); getAssetsStub.resolves(); downloadAssetsStub.resolves(); getVersionedAssetsStub.resolves(); - + // Stub progress manager methods to avoid issues sinon.stub(exportAssets as any, 'createNestedProgress').returns({ addProcess: sinon.stub(), startProcess: sinon.stub().returns({ - updateStatus: sinon.stub() + updateStatus: sinon.stub(), }), updateStatus: sinon.stub(), completeProcess: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), } as any); sinon.stub(exportAssets as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { return await fn(); @@ -330,7 +328,7 @@ describe('ExportAssets', () => { it('should export versioned assets when enabled', async () => { mockExportConfig.modules.assets.includeVersionedAssets = true; exportAssets.versionedAssets = [{ 'asset-1': 2 }]; - + // Just verify the flow completes await exportAssets.start(); @@ -365,8 +363,8 @@ describe('ExportAssets', () => { it('should handle errors gracefully', async () => { mockStackClient.asset = sinon.stub().returns({ query: sinon.stub().returns({ - count: sinon.stub().rejects(new Error('API Error')) - }) + count: sinon.stub().rejects(new Error('API Error')), + }), }); const count = await exportAssets.getAssetsCount(false); @@ -507,7 +505,7 @@ describe('ExportAssets', () => { it('should handle onReject callback for versioned assets errors', async () => { exportAssets.versionedAssets = [{ 'asset-1': 2 }]; - + makeConcurrentCallStub.callsFake(async (options: any) => { const onReject = options.apiParams.reject; const error = new Error('Versioned asset query failed'); @@ -518,7 +516,6 @@ describe('ExportAssets', () => { await exportAssets.getVersionedAssets(); expect(makeConcurrentCallStub.called).to.be.true; }); - }); describe('downloadAssets() method', () => { @@ -558,7 +555,7 @@ describe('ExportAssets', () => { it('should include versioned assets when enabled', async () => { mockExportConfig.modules.assets.includeVersionedAssets = true; - + await exportAssets.downloadAssets(); // Should complete without error @@ -567,7 +564,7 @@ describe('ExportAssets', () => { it('should handle download with secured assets', async () => { mockExportConfig.modules.assets.securedAssets = true; - + await exportAssets.downloadAssets(); expect(makeConcurrentCallStub.called).to.be.true; @@ -575,7 +572,7 @@ describe('ExportAssets', () => { it('should handle download with enabled status', async () => { mockExportConfig.modules.assets.enableDownloadStatus = true; - + makeConcurrentCallStub.callsFake(async (options: any, handler: any) => { expect(options.totalCount).to.be.greaterThan(0); }); @@ -608,7 +605,7 @@ describe('ExportAssets', () => { it('should handle versioned assets with version 1 only', async () => { exportAssets.versionedAssets = []; - + const result = await exportAssets.getVersionedAssets(); // Should complete without errors expect(result).to.be.undefined; @@ -639,14 +636,14 @@ describe('ExportAssets', () => { const assetsWithDuplicates = { 'file-1': [ { uid: '1', url: 'same-url', filename: 'test.jpg' }, - { uid: '2', url: 'same-url', filename: 'test.jpg' } - ] + { uid: '2', url: 'same-url', filename: 'test.jpg' }, + ], }; sinon.stub(FsUtility.prototype, 'getPlainMeta').returns(assetsWithDuplicates); const makeConcurrentCallStub = sinon.stub(exportAssets as any, 'makeConcurrentCall').resolves(); await exportAssets.downloadAssets(); - + // Should only download unique assets sinon.restore(); }); @@ -654,26 +651,26 @@ describe('ExportAssets', () => { it('should handle download assets with versioned metadata', async () => { mockExportConfig.modules.assets.includeVersionedAssets = true; (exportAssets as any).assetsRootPath = '/test/data/assets'; - + const mainAssets = { 'file-1': [{ uid: '1', url: 'url1', filename: 'test.jpg' }] }; const versionedAssets = { 'file-2': [{ uid: '2', url: 'url2', filename: 'version.jpg' }] }; - + const getPlainMetaStub = sinon.stub(FsUtility.prototype, 'getPlainMeta'); getPlainMetaStub.onFirstCall().returns(mainAssets); getPlainMetaStub.onSecondCall().returns(versionedAssets); - + // Mock getDirectories to return empty array to avoid fs operations sinon.stub(exportAssets as any, 'assetsRootPath').get(() => '/test/data/assets'); const makeConcurrentCallStub = sinon.stub(exportAssets as any, 'makeConcurrentCall').resolves(); - + // Create a simple mock for getDirectories behavior const fsInstance: any = { getPlainMeta: getPlainMetaStub, - createFolderIfNotExist: () => {} + createFolderIfNotExist: () => {}, }; - + await exportAssets.downloadAssets(); - + expect(makeConcurrentCallStub.called).to.be.true; sinon.restore(); }); @@ -695,11 +692,11 @@ describe('ExportAssets', () => { it('should handle assets with no items response', async () => { (exportAssets as any).assetsRootPath = '/test/data/assets'; - + // Stub FsUtility methods sinon.stub(FsUtility.prototype, 'writeIntoFile').resolves(); sinon.stub(FsUtility.prototype, 'completeFile').resolves(); - + makeConcurrentCallStub.callsFake(async (options: any) => { const onSuccess = options.apiParams.resolve; onSuccess({ response: { items: [] } }); @@ -712,22 +709,22 @@ describe('ExportAssets', () => { it('should handle assets with versioned assets enabled', async () => { (exportAssets as any).assetsRootPath = '/test/data/assets'; mockExportConfig.modules.assets.includeVersionedAssets = true; - + // Stub FsUtility methods to prevent fs operations sinon.stub(FsUtility.prototype, 'writeIntoFile').resolves(); sinon.stub(FsUtility.prototype, 'completeFile').resolves(); sinon.stub(FsUtility.prototype, 'createFolderIfNotExist').resolves(); - + makeConcurrentCallStub.callsFake(async (options: any) => { const onSuccess = options.apiParams.resolve; // Mock versioned assets - onSuccess({ - response: { + onSuccess({ + response: { items: [ { uid: '1', _version: 2, url: 'url1', filename: 'test.jpg' }, - { uid: '2', _version: 1, url: 'url2', filename: 'test2.jpg' } - ] - } + { uid: '2', _version: 1, url: 'url2', filename: 'test2.jpg' }, + ], + }, }); }); @@ -738,12 +735,12 @@ describe('ExportAssets', () => { it('should apply query filters when configured', async () => { (exportAssets as any).assetsRootPath = '/test/data/assets'; mockExportConfig.modules.assets.invalidKeys = ['SYS_ACL']; - + // Stub FsUtility methods to prevent fs operations sinon.stub(FsUtility.prototype, 'writeIntoFile').resolves(); sinon.stub(FsUtility.prototype, 'completeFile').resolves(); sinon.stub(FsUtility.prototype, 'createFolderIfNotExist').resolves(); - + makeConcurrentCallStub.callsFake(async (options: any) => { const onSuccess = options.apiParams.resolve; onSuccess({ response: { items: [{ uid: '1', url: 'url1', filename: 'test.jpg' }] } }); @@ -758,7 +755,7 @@ describe('ExportAssets', () => { it('should handle folders with empty items response', async () => { (exportAssets as any).assetsRootPath = '/test/data/assets'; const makeConcurrentCallStub = sinon.stub(exportAssets as any, 'makeConcurrentCall').resolves(); - + makeConcurrentCallStub.callsFake(async (options: any) => { const onSuccess = options.apiParams.resolve; onSuccess({ response: { items: [] } }); @@ -766,19 +763,19 @@ describe('ExportAssets', () => { await exportAssets.getAssetsFolders(10); expect(makeConcurrentCallStub.called).to.be.true; - + makeConcurrentCallStub.restore(); }); it('should add folders to assetsFolder array', async () => { (exportAssets as any).assetsRootPath = '/test/data/assets'; - + const makeConcurrentCallStub = sinon.stub(exportAssets as any, 'makeConcurrentCall').resolves(); - + // Stub FsUtility methods to prevent file system operations sinon.stub(FsUtility.prototype, 'writeFile').resolves(); sinon.stub(FsUtility.prototype, 'createFolderIfNotExist').resolves(); - + makeConcurrentCallStub.callsFake(async (options: any) => { const onSuccess = options.apiParams.resolve; // Simulate adding folders to the array @@ -787,11 +784,11 @@ describe('ExportAssets', () => { }); await exportAssets.getAssetsFolders(10); - + expect(makeConcurrentCallStub.called).to.be.true; // Verify folders were added expect((exportAssets as any).assetsFolder.length).to.be.greaterThan(0); - + makeConcurrentCallStub.restore(); }); }); @@ -800,14 +797,14 @@ describe('ExportAssets', () => { it('should handle download with secured assets', async () => { mockExportConfig.modules.assets.securedAssets = true; (exportAssets as any).assetsRootPath = '/test/data/assets'; - + const getPlainMetaStub = sinon.stub(FsUtility.prototype, 'getPlainMeta').returns({ - 'file-1': [{ uid: '1', url: 'url1', filename: 'test.jpg' }] + 'file-1': [{ uid: '1', url: 'url1', filename: 'test.jpg' }], }); const makeConcurrentCallStub = sinon.stub(exportAssets as any, 'makeConcurrentCall').resolves(); - + await exportAssets.downloadAssets(); - + expect(makeConcurrentCallStub.called).to.be.true; getPlainMetaStub.restore(); makeConcurrentCallStub.restore(); @@ -816,14 +813,14 @@ describe('ExportAssets', () => { it('should handle download with enableDownloadStatus', async () => { mockExportConfig.modules.assets.enableDownloadStatus = true; (exportAssets as any).assetsRootPath = '/test/data/assets'; - + const getPlainMetaStub = sinon.stub(FsUtility.prototype, 'getPlainMeta').returns({ - 'file-1': [{ uid: '1', url: 'url1', filename: 'test.jpg' }] + 'file-1': [{ uid: '1', url: 'url1', filename: 'test.jpg' }], }); const makeConcurrentCallStub = sinon.stub(exportAssets as any, 'makeConcurrentCall').resolves(); - + await exportAssets.downloadAssets(); - + expect(makeConcurrentCallStub.called).to.be.true; getPlainMetaStub.restore(); makeConcurrentCallStub.restore(); @@ -831,18 +828,17 @@ describe('ExportAssets', () => { it('should handle download with concurrent call structure', async () => { (exportAssets as any).assetsRootPath = '/test/data/assets'; - + const getPlainMetaStub = sinon.stub(FsUtility.prototype, 'getPlainMeta').returns({ - 'file-1': [{ uid: '1', url: 'url1', filename: 'test.jpg' }] + 'file-1': [{ uid: '1', url: 'url1', filename: 'test.jpg' }], }); const makeConcurrentCallStub = sinon.stub(exportAssets as any, 'makeConcurrentCall').resolves(); - + await exportAssets.downloadAssets(); - + expect(makeConcurrentCallStub.called).to.be.true; getPlainMetaStub.restore(); makeConcurrentCallStub.restore(); }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/base-class.test.ts b/packages/contentstack-export/test/unit/export/modules/base-class.test.ts index ebf3ea51dd..12e913a348 100644 --- a/packages/contentstack-export/test/unit/export/modules/base-class.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/base-class.test.ts @@ -23,24 +23,23 @@ describe('BaseClass', () => { fetch: sinon.stub().resolves({ uid: 'asset-123', title: 'Test Asset' }), query: sinon.stub().returns({ find: sinon.stub().resolves({ - items: [{ uid: 'asset-1' }, { uid: 'asset-2' }] - }) + items: [{ uid: 'asset-1' }, { uid: 'asset-2' }], + }), }), - download: sinon.stub().resolves({ data: 'stream-data' }) + download: sinon.stub().resolves({ data: 'stream-data' }), }), contentType: sinon.stub().returns({ - fetch: sinon.stub().resolves({ uid: 'ct-123' }) + fetch: sinon.stub().resolves({ uid: 'ct-123' }), }), entry: sinon.stub().returns({ - fetch: sinon.stub().resolves({ uid: 'entry-123' }) + fetch: sinon.stub().resolves({ uid: 'entry-123' }), }), taxonomy: sinon.stub().returns({ - export: sinon.stub().resolves({ data: 'taxonomy-export' }) - }) + export: sinon.stub().resolves({ data: 'taxonomy-export' }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -55,7 +54,7 @@ describe('BaseClass', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -64,7 +63,7 @@ describe('BaseClass', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -81,7 +80,7 @@ describe('BaseClass', () => { users: '', extension: '', webhooks: '', - stacks: '' + stacks: '', }, preserveStackVersion: false, personalizationEnabled: false, @@ -89,57 +88,56 @@ describe('BaseClass', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['assets'], locales: { dirName: 'locales', fileName: 'locales.json', - requiredKeys: ['code'] + requiredKeys: ['code'], }, customRoles: { dirName: 'custom_roles', fileName: 'custom_roles.json', - customRolesLocalesFileName: '' + customRolesLocalesFileName: '', }, 'custom-roles': { dirName: 'custom_roles', fileName: 'custom_roles.json', - customRolesLocalesFileName: '' + customRolesLocalesFileName: '', }, environments: { dirName: 'environments', - fileName: 'environments.json' + fileName: 'environments.json', }, labels: { dirName: 'labels', fileName: 'labels.json', - invalidKeys: [] + invalidKeys: [], }, webhooks: { dirName: 'webhooks', - fileName: 'webhooks.json' + fileName: 'webhooks.json', }, releases: { dirName: 'releases', fileName: 'releases.json', releasesList: 'releases_list.json', - invalidKeys: [] + invalidKeys: [], }, workflows: { dirName: 'workflows', fileName: 'workflows.json', - invalidKeys: [] + invalidKeys: [], }, globalfields: { dirName: 'global_fields', fileName: 'globalfields.json', - validKeys: ['title', 'uid'] + validKeys: ['title', 'uid'], }, 'global-fields': { dirName: 'global_fields', fileName: 'globalfields.json', - validKeys: ['title', 'uid'] + validKeys: ['title', 'uid'], }, assets: { dirName: 'assets', @@ -154,19 +152,19 @@ describe('BaseClass', () => { securedAssets: false, displayExecutionTime: false, enableDownloadStatus: false, - includeVersionedAssets: false + includeVersionedAssets: false, }, content_types: { dirName: 'content_types', fileName: 'content_types.json', validKeys: ['title', 'uid'], - limit: 100 + limit: 100, }, 'content-types': { dirName: 'content_types', fileName: 'content_types.json', validKeys: ['title', 'uid'], - limit: 100 + limit: 100, }, entries: { dirName: 'entries', @@ -175,75 +173,75 @@ describe('BaseClass', () => { batchLimit: 100, downloadLimit: 5, limit: 100, - exportVersions: false + exportVersions: false, }, personalize: { dirName: 'personalize', - baseURL: {} + baseURL: {}, }, variantEntry: { dirName: 'variant_entries', fileName: 'variant_entries.json', chunkFileSize: 5, - query: { skip: 0, limit: 100, include_variant: true, include_count: false, include_publish_details: true } + query: { skip: 0, limit: 100, include_variant: true, include_count: false, include_publish_details: true }, }, extensions: { dirName: 'extensions', - fileName: 'extensions.json' + fileName: 'extensions.json', }, stack: { dirName: 'stack', - fileName: 'stack.json' + fileName: 'stack.json', }, dependency: { - entries: [] + entries: [], }, marketplace_apps: { dirName: 'marketplace_apps', - fileName: 'marketplace_apps.json' + fileName: 'marketplace_apps.json', }, 'marketplace-apps': { dirName: 'marketplace_apps', - fileName: 'marketplace_apps.json' + fileName: 'marketplace_apps.json', }, 'composable-studio': { dirName: 'composable-studio', fileName: 'composable-studio.json', apiBaseUrl: 'https://api.contentstack.io', - apiVersion: 'v1' + apiVersion: 'v1', }, masterLocale: { dirName: 'master_locale', fileName: 'master_locale.json', - requiredKeys: ['code'] + requiredKeys: ['code'], }, taxonomies: { dirName: 'taxonomies', fileName: 'taxonomies.json', invalidKeys: [], - limit: 100 + limit: 100, }, events: { dirName: 'events', fileName: 'events.json', - invalidKeys: [] + invalidKeys: [], }, audiences: { dirName: 'audiences', fileName: 'audiences.json', - invalidKeys: [] + invalidKeys: [], }, attributes: { dirName: 'attributes', fileName: 'attributes.json', - invalidKeys: [] - } - } + invalidKeys: [], + }, + }, } as ExportConfig; testClass = new TestBaseClass({ exportConfig: mockExportConfig, - stackAPIClient: mockStackClient + stackAPIClient: mockStackClient, }); }); @@ -323,8 +321,8 @@ describe('BaseClass', () => { apiParams: { module: 'assets', resolve: sinon.stub(), - reject: sinon.stub() - } + reject: sinon.stub(), + }, }; await testClass.makeConcurrentCall(env); @@ -339,8 +337,8 @@ describe('BaseClass', () => { apiParams: { module: 'asset', resolve: sinon.stub(), - reject: sinon.stub() - } + reject: sinon.stub(), + }, }; const result = await testClass.makeConcurrentCall(env); @@ -356,7 +354,7 @@ describe('BaseClass', () => { const env: EnvType = { module: 'test', totalCount: 150, - concurrencyLimit: 5 + concurrencyLimit: 5, }; await testClass.makeConcurrentCall(env, customHandler); @@ -372,7 +370,7 @@ describe('BaseClass', () => { const env: EnvType = { module: 'test', totalCount: 300, - concurrencyLimit: 2 + concurrencyLimit: 2, }; await testClass.makeConcurrentCall(env, customHandler); @@ -384,7 +382,7 @@ describe('BaseClass', () => { const env: EnvType = { module: 'test', totalCount: 100, - concurrencyLimit: 10 + concurrencyLimit: 10, }; const result = await testClass.makeConcurrentCall(env); @@ -401,8 +399,8 @@ describe('BaseClass', () => { uid: 'asset-123', resolve: sinon.stub(), reject: sinon.stub(), - queryParam: {} - } + queryParam: {}, + }, }; await testClass.makeConcurrentCall(env); @@ -418,8 +416,8 @@ describe('BaseClass', () => { module: 'assets', resolve: sinon.stub(), reject: sinon.stub(), - queryParam: { skip: 0 } - } + queryParam: { skip: 0 }, + }, }; await testClass.makeConcurrentCall(env); @@ -436,8 +434,8 @@ describe('BaseClass', () => { url: 'https://example.com/asset.jpg', resolve: sinon.stub(), reject: sinon.stub(), - queryParam: {} - } + queryParam: {}, + }, }; await testClass.makeConcurrentCall(env); @@ -454,8 +452,8 @@ describe('BaseClass', () => { uid: 'taxonomy-123', resolve: sinon.stub(), reject: sinon.stub(), - queryParam: {} - } + queryParam: {}, + }, }; await testClass.makeConcurrentCall(env); @@ -466,7 +464,7 @@ describe('BaseClass', () => { const env: EnvType = { module: 'test', totalCount: 100, - concurrencyLimit: 5 + concurrencyLimit: 5, }; let isLastRequestValues: boolean[] = []; @@ -483,7 +481,7 @@ describe('BaseClass', () => { it('should handle API errors gracefully', async () => { const error = new Error('API Error'); mockStackClient.asset = sinon.stub().returns({ - fetch: sinon.stub().rejects(error) + fetch: sinon.stub().rejects(error), }); const env: EnvType = { @@ -497,8 +495,8 @@ describe('BaseClass', () => { reject: (error) => { expect(error.error).to.equal(error); }, - queryParam: {} - } + queryParam: {}, + }, }; await testClass.makeConcurrentCall(env); @@ -507,22 +505,22 @@ describe('BaseClass', () => { it('should provide correct batch and index information', async () => { const batchInfo: Array<{ batchIndex: number; index: number }> = []; - + const customHandler: CustomPromiseHandler = async (input) => { batchInfo.push({ batchIndex: input.batchIndex, - index: input.index + index: input.index, }); }; const env: EnvType = { module: 'test', totalCount: 250, - concurrencyLimit: 5 + concurrencyLimit: 5, }; await testClass.makeConcurrentCall(env, customHandler); - + // Verify batch and index information expect(batchInfo.length).to.be.greaterThan(0); expect(batchInfo[0]?.batchIndex).to.be.a('number'); @@ -541,37 +539,37 @@ describe('BaseClass', () => { it('should log batch completion', async () => { const start = Date.now(); - + await (testClass as any).logMsgAndWaitIfRequired('test-module', start, 1); - + // Just verify it completes without error - the log is tested implicitly }); - it('should wait when execution time is less than 1000ms', async function() { + it('should wait when execution time is less than 1000ms', async function () { clock = sinon.useFakeTimers(); const start = Date.now(); - + const waitPromise = (testClass as any).logMsgAndWaitIfRequired('test-module', start, 1); clock.tick(1000); await waitPromise; - + // Just verify it completes clock.restore(); }); it('should not wait when execution time is more than 1000ms', async () => { const start = Date.now() - 1500; - + await (testClass as any).logMsgAndWaitIfRequired('test-module', start, 1); - + // Just verify it completes }); it('should display execution time when configured', async () => { mockExportConfig.modules.assets.displayExecutionTime = true; - + await (testClass as any).logMsgAndWaitIfRequired('test-module', Date.now() - 100, 1); - + // Verify it completes - display logic is tested implicitly }); }); @@ -586,7 +584,7 @@ describe('BaseClass', () => { uid: 'asset-123', queryParam: {}, resolve: resolveStub, - reject: rejectStub + reject: rejectStub, }); expect(mockStackClient.asset.calledWith('asset-123')).to.be.true; @@ -600,7 +598,7 @@ describe('BaseClass', () => { module: 'assets', queryParam: { skip: 0 }, resolve: resolveStub, - reject: rejectStub + reject: rejectStub, }); expect(mockStackClient.asset.called).to.be.true; @@ -609,7 +607,7 @@ describe('BaseClass', () => { it('should handle API errors', async () => { const error = new Error('Network error'); mockStackClient.asset = sinon.stub().returns({ - fetch: sinon.stub().rejects(error) + fetch: sinon.stub().rejects(error), }); const rejectStub = sinon.stub(); @@ -619,7 +617,7 @@ describe('BaseClass', () => { uid: 'asset-123', queryParam: {}, resolve: sinon.stub(), - reject: rejectStub + reject: rejectStub, }); // Error should be handled by reject @@ -629,7 +627,7 @@ describe('BaseClass', () => { const result = await (testClass as any).makeAPICall({ module: 'unknown' as any, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }); expect(result).to.be.undefined; @@ -641,7 +639,7 @@ describe('BaseClass', () => { const env: EnvType = { module: 'test', totalCount: 100, - concurrencyLimit: 5 + concurrencyLimit: 5, }; const result = await testClass.makeConcurrentCall(env); @@ -652,7 +650,7 @@ describe('BaseClass', () => { const env: EnvType = { module: 'test', totalCount: 101, - concurrencyLimit: 5 + concurrencyLimit: 5, }; const result = await testClass.makeConcurrentCall(env); @@ -663,7 +661,7 @@ describe('BaseClass', () => { const env: EnvType = { module: 'test', totalCount: 50, - concurrencyLimit: 1 + concurrencyLimit: 1, }; const result = await testClass.makeConcurrentCall(env); @@ -674,7 +672,7 @@ describe('BaseClass', () => { const env: EnvType = { module: 'test', totalCount: 50, - concurrencyLimit: 100 + concurrencyLimit: 100, }; const result = await testClass.makeConcurrentCall(env); @@ -682,4 +680,3 @@ describe('BaseClass', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/content-types.test.ts b/packages/contentstack-export/test/unit/export/modules/content-types.test.ts index 44bda7dd50..e37aacc2db 100644 --- a/packages/contentstack-export/test/unit/export/modules/content-types.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/content-types.test.ts @@ -16,16 +16,15 @@ describe('ExportContentTypes', () => { find: sinon.stub().resolves({ items: [ { uid: 'ct-1', title: 'Content Type 1', description: 'Description', invalidKey: 'remove' }, - { uid: 'ct-2', title: 'Content Type 2', description: 'Description', invalidKey: 'remove' } + { uid: 'ct-2', title: 'Content Type 2', description: 'Description', invalidKey: 'remove' }, ], - count: 2 - }) - }) - }) + count: 2, + }), + }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -42,7 +41,7 @@ describe('ExportContentTypes', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -51,7 +50,7 @@ describe('ExportContentTypes', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -63,7 +62,6 @@ describe('ExportContentTypes', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['content-types'], 'content-types': { @@ -72,15 +70,15 @@ describe('ExportContentTypes', () => { validKeys: ['uid', 'title', 'description', 'schema'], fetchConcurrency: 5, writeConcurrency: 5, - limit: 100 - } - } + limit: 100, + }, + }, } as any; exportContentTypes = new ExportContentTypes({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'content-types' + moduleName: 'content-types', }); // Stub FsUtility methods @@ -110,7 +108,7 @@ describe('ExportContentTypes', () => { expect((exportContentTypes as any).qs).to.deep.include({ include_count: true, asc: 'updated_at', - include_global_field_schema: true + include_global_field_schema: true, }); }); @@ -122,13 +120,13 @@ describe('ExportContentTypes', () => { it('should set uid filter when contentTypes are provided', () => { const configWithTypes = { ...mockExportConfig, - contentTypes: ['ct-1', 'ct-2'] + contentTypes: ['ct-1', 'ct-2'], }; const instance = new ExportContentTypes({ exportConfig: configWithTypes, stackAPIClient: mockStackClient, - moduleName: 'content-types' + moduleName: 'content-types', }); expect((instance as any).qs.uid).to.deep.equal({ $in: ['ct-1', 'ct-2'] }); @@ -139,16 +137,16 @@ describe('ExportContentTypes', () => { it('should fetch and process content types correctly', async () => { const contentTypes = [ { uid: 'ct-1', title: 'Type 1', description: 'Desc', invalidKey: 'remove' }, - { uid: 'ct-2', title: 'Type 2', description: 'Desc', invalidKey: 'remove' } + { uid: 'ct-2', title: 'Type 2', description: 'Desc', invalidKey: 'remove' }, ]; mockStackClient.contentType.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: contentTypes, - count: 2 - }) - }) + count: 2, + }), + }), }); await exportContentTypes.getContentTypes(); @@ -170,16 +168,16 @@ describe('ExportContentTypes', () => { if (callCount === 1) { return Promise.resolve({ items: new Array(100).fill({ uid: 'test', title: 'Test', description: 'Desc' }), - count: 150 + count: 150, }); } else { return Promise.resolve({ items: new Array(50).fill({ uid: 'test2', title: 'Test2', description: 'Desc' }), - count: 150 + count: 150, }); } - }) - }) + }), + }), }); await exportContentTypes.getContentTypes(); @@ -192,8 +190,8 @@ describe('ExportContentTypes', () => { it('should handle API errors and log them', async () => { mockStackClient.contentType.returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(new Error('API Error')) - }) + find: sinon.stub().rejects(new Error('API Error')), + }), }); try { @@ -209,9 +207,9 @@ describe('ExportContentTypes', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = exportContentTypes.contentTypes.length; @@ -226,11 +224,11 @@ describe('ExportContentTypes', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [{ uid: 'ct-1', title: 'Test', description: 'Desc' }], - count: 1 - }) - }) + count: 1, + }), + }), }); - + await exportContentTypes.getContentTypes(50); // Verify skip was set in query @@ -242,7 +240,7 @@ describe('ExportContentTypes', () => { it('should sanitize content type attributes and remove invalid keys', () => { const contentTypes = [ { uid: 'ct-1', title: 'Type 1', description: 'Desc', invalidKey: 'remove' }, - { uid: 'ct-2', title: 'Type 2', description: 'Desc', invalidKey: 'remove' } + { uid: 'ct-2', title: 'Type 2', description: 'Desc', invalidKey: 'remove' }, ]; const result = exportContentTypes.sanitizeAttribs(contentTypes); @@ -254,9 +252,7 @@ describe('ExportContentTypes', () => { }); it('should handle content types without required keys', () => { - const contentTypes = [ - { uid: 'ct-1', invalidKey: 'remove' } - ]; + const contentTypes = [{ uid: 'ct-1', invalidKey: 'remove' }]; const result = exportContentTypes.sanitizeAttribs(contentTypes); @@ -278,7 +274,7 @@ describe('ExportContentTypes', () => { const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; const contentTypes = [ { uid: 'ct-1', title: 'Type 1', description: 'Desc' }, - { uid: 'ct-2', title: 'Type 2', description: 'Desc' } + { uid: 'ct-2', title: 'Type 2', description: 'Desc' }, ]; await exportContentTypes.writeContentTypes(contentTypes); @@ -295,16 +291,16 @@ describe('ExportContentTypes', () => { const contentTypes = [ { uid: 'ct-1', title: 'Type 1', description: 'Desc' }, - { uid: 'ct-2', title: 'Type 2', description: 'Desc' } + { uid: 'ct-2', title: 'Type 2', description: 'Desc' }, ]; mockStackClient.contentType.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: contentTypes, - count: 2 - }) - }) + count: 2, + }), + }), }); await exportContentTypes.start(); @@ -323,9 +319,9 @@ describe('ExportContentTypes', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); exportContentTypes.contentTypes = []; @@ -338,8 +334,8 @@ describe('ExportContentTypes', () => { it('should handle errors during export without throwing', async () => { mockStackClient.contentType.returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(new Error('Export failed')) - }) + find: sinon.stub().rejects(new Error('Export failed')), + }), }); // Should complete without throwing @@ -347,4 +343,3 @@ describe('ExportContentTypes', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/custom-roles.test.ts b/packages/contentstack-export/test/unit/export/modules/custom-roles.test.ts index 715453a5fe..f052039095 100644 --- a/packages/contentstack-export/test/unit/export/modules/custom-roles.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/custom-roles.test.ts @@ -16,23 +16,20 @@ describe('ExportCustomRoles', () => { items: [ { uid: 'custom-role-1', name: 'Custom Role 1' }, { uid: 'Admin', name: 'Admin' }, - { uid: 'Developer', name: 'Developer' } - ] - }) + { uid: 'Developer', name: 'Developer' }, + ], + }), }), locale: sinon.stub().returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ - items: [ - { uid: 'locale-1', name: 'English', code: 'en-us' } - ] - }) - }) - }) + items: [{ uid: 'locale-1', name: 'English', code: 'en-us' }], + }), + }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -48,7 +45,7 @@ describe('ExportCustomRoles', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -57,7 +54,7 @@ describe('ExportCustomRoles', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -69,21 +66,20 @@ describe('ExportCustomRoles', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['custom-roles'], customRoles: { dirName: 'custom_roles', fileName: 'custom_roles.json', - customRolesLocalesFileName: 'custom_roles_locales.json' - } - } + customRolesLocalesFileName: 'custom_roles_locales.json', + }, + }, } as any; exportCustomRoles = new ExportCustomRoles({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'custom-roles' + moduleName: 'custom-roles', }); // Stub FsUtility methods @@ -118,7 +114,7 @@ describe('ExportCustomRoles', () => { expect(exportCustomRoles.existingRoles).to.deep.equal({ Admin: 1, Developer: 1, - 'Content Manager': 1 + 'Content Manager': 1, }); }); }); @@ -127,7 +123,7 @@ describe('ExportCustomRoles', () => { it('should fetch and filter only custom roles', async () => { // Set rolesFolderPath before calling exportCustomRoles.rolesFolderPath = '/test/data/custom_roles'; - + await exportCustomRoles.getCustomRoles(); // Verify only custom role was added (not Admin or Developer) @@ -138,18 +134,18 @@ describe('ExportCustomRoles', () => { it('should handle no custom roles found', async () => { exportCustomRoles.rolesFolderPath = '/test/data/custom_roles'; - + mockStackClient.role.returns({ fetchAll: sinon.stub().resolves({ items: [ { uid: 'Admin', name: 'Admin' }, - { uid: 'Developer', name: 'Developer' } - ] - }) + { uid: 'Developer', name: 'Developer' }, + ], + }), }); const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; - + await exportCustomRoles.getCustomRoles(); // Verify no custom roles were added @@ -158,16 +154,16 @@ describe('ExportCustomRoles', () => { it('should handle API errors gracefully without crashing', async () => { exportCustomRoles.rolesFolderPath = '/test/data/custom_roles'; - + // Mock to return valid data structure with no items to avoid undefined mockStackClient.role.returns({ fetchAll: sinon.stub().resolves({ - items: [] - }) + items: [], + }), }); await exportCustomRoles.getCustomRoles(); - + // Verify method completed without throwing expect(Object.keys(exportCustomRoles.customRoles).length).to.equal(0); }); @@ -186,13 +182,13 @@ describe('ExportCustomRoles', () => { mockStackClient.locale.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ - items: [] - }) - }) + items: [], + }), + }), }); await exportCustomRoles.getLocales(); - + // Verify method completed expect(exportCustomRoles.sourceLocalesMap).to.be.an('object'); }); @@ -206,15 +202,15 @@ describe('ExportCustomRoles', () => { rules: [ { module: 'locale', - locales: ['locale-1', 'locale-2'] - } - ] - } + locales: ['locale-1', 'locale-2'], + }, + ], + }, }; exportCustomRoles.sourceLocalesMap = { 'locale-1': { uid: 'locale-1', name: 'English' }, - 'locale-2': { uid: 'locale-2', name: 'Spanish' } + 'locale-2': { uid: 'locale-2', name: 'Spanish' }, }; await exportCustomRoles.getCustomRolesLocales(); @@ -227,8 +223,8 @@ describe('ExportCustomRoles', () => { exportCustomRoles.customRoles = { 'custom-role-1': { name: 'Custom Role 1', - rules: [] - } + rules: [], + }, }; await exportCustomRoles.getCustomRolesLocales(); @@ -253,16 +249,16 @@ describe('ExportCustomRoles', () => { // Mock to return empty result to avoid undefined issues mockStackClient.role.returns({ fetchAll: sinon.stub().resolves({ - items: [] - }) + items: [], + }), }); - + mockStackClient.locale.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ - items: [] - }) - }) + items: [], + }), + }), }); // Should complete without throwing @@ -270,4 +266,3 @@ describe('ExportCustomRoles', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/entries.test.ts b/packages/contentstack-export/test/unit/export/modules/entries.test.ts index e06a402887..e747f5802f 100644 --- a/packages/contentstack-export/test/unit/export/modules/entries.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/entries.test.ts @@ -22,7 +22,7 @@ describe('EntriesExport', () => { // Mock stack API client mockStackAPIClient = { - contentType: sandbox.stub() + contentType: sandbox.stub(), }; // Set default return value mockStackAPIClient.contentType.returns({ @@ -30,16 +30,15 @@ describe('EntriesExport', () => { query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: [], - count: 0 - }) + count: 0, + }), }), - fetch: sandbox.stub().resolves({}) - }) + fetch: sandbox.stub().resolves({}), + }), }); // Mock ExportConfig mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -55,7 +54,7 @@ describe('EntriesExport', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -64,7 +63,7 @@ describe('EntriesExport', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -76,7 +75,6 @@ describe('EntriesExport', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['entries'], entries: { @@ -86,48 +84,48 @@ describe('EntriesExport', () => { limit: 100, chunkFileSize: 1000, batchLimit: 5, - exportVersions: false + exportVersions: false, }, locales: { dirName: 'locales', - fileName: 'locales.json' + fileName: 'locales.json', }, content_types: { dirName: 'content_types', - fileName: 'schema.json' + fileName: 'schema.json', }, personalize: { baseURL: { - 'us': 'https://personalize-api.contentstack.com', + us: 'https://personalize-api.contentstack.com', 'AWS-NA': 'https://personalize-api.contentstack.com', - 'AWS-EU': 'https://eu-personalize-api.contentstack.com' + 'AWS-EU': 'https://eu-personalize-api.contentstack.com', }, dirName: 'personalize', - exportOrder: [] - } + exportOrder: [], + }, }, org_uid: 'test-org-uid', - query: {} + query: {}, } as any; // Mock fsUtil mockFsUtil = { readFile: sandbox.stub(), makeDirectory: sandbox.stub().resolves(), - writeFile: sandbox.stub() + writeFile: sandbox.stub(), }; sandbox.stub(fsUtilModule, 'fsUtil').value(mockFsUtil); // Mock ExportProjects mockExportProjects = { init: sandbox.stub().resolves(), - projects: sandbox.stub().resolves([]) + projects: sandbox.stub().resolves([]), }; sandbox.stub(variants, 'ExportProjects').callsFake(() => mockExportProjects as any); // Mock VariantEntries mockVariantEntries = { - exportVariantEntry: sandbox.stub().resolves() + exportVariantEntry: sandbox.stub().resolves(), }; sandbox.stub(variants.Export, 'VariantEntries').callsFake(() => mockVariantEntries as any); @@ -146,7 +144,7 @@ describe('EntriesExport', () => { entriesExport = new EntriesExport({ exportConfig: mockExportConfig, stackAPIClient: mockStackAPIClient, - moduleName: 'entries' + moduleName: 'entries', }); }); @@ -165,21 +163,21 @@ describe('EntriesExport', () => { it('should set up correct directory paths based on exportConfig', () => { const expectedEntriesPath = path.resolve( - mockExportConfig.data, + mockExportConfig.exportDir, mockExportConfig.branchName || '', - mockExportConfig.modules.entries.dirName + mockExportConfig.modules.entries.dirName, ); const expectedLocalesPath = path.resolve( - mockExportConfig.data, + mockExportConfig.exportDir, mockExportConfig.branchName || '', mockExportConfig.modules.locales.dirName, - mockExportConfig.modules.locales.fileName + mockExportConfig.modules.locales.fileName, ); const expectedSchemaPath = path.resolve( - mockExportConfig.data, + mockExportConfig.exportDir, mockExportConfig.branchName || '', mockExportConfig.modules.content_types.dirName, - 'schema.json' + 'schema.json', ); expect(entriesExport.entriesDirPath).to.equal(expectedEntriesPath); @@ -242,12 +240,12 @@ describe('EntriesExport', () => { query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }; const contentTypeStub = sandbox.stub().returns({ - entry: sandbox.stub().returns(mockEntryQuery) + entry: sandbox.stub().returns(mockEntryQuery), }); // Update both the mock and entriesExport to use the new stub mockStackAPIClient.contentType = contentTypeStub; @@ -271,11 +269,7 @@ describe('EntriesExport', () => { const locales = [{ code: 'en-us' }]; const contentTypes = [{ uid: 'ct-1', title: 'Content Type 1' }]; - mockFsUtil.readFile - .onFirstCall() - .returns(locales) - .onSecondCall() - .returns(contentTypes); + mockFsUtil.readFile.onFirstCall().returns(locales).onSecondCall().returns(contentTypes); // Mock successful entry fetch - use callsFake to preserve call tracking const contentTypeStub = sandbox.stub().returns({ @@ -283,10 +277,10 @@ describe('EntriesExport', () => { query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: [], - count: 0 - }) - }) - }) + count: 0, + }), + }), + }), }); mockStackAPIClient.contentType = contentTypeStub; // Update entriesExport to use the new mock @@ -304,7 +298,7 @@ describe('EntriesExport', () => { const variantEntriesStub = variants.Export.VariantEntries as unknown as sinon.SinonStub; expect(variantEntriesStub.called).to.be.true; expect(variantEntriesStub.firstCall.args[0]).to.include({ - project_id: 'project-123' + project_id: 'project-123', }); // Verify the flow completed successfully // The key behavior is that exportVariantEntry is enabled when project is found @@ -321,21 +315,17 @@ describe('EntriesExport', () => { const locales = [{ code: 'en-us' }]; const contentTypes = [{ uid: 'ct-1', title: 'Content Type 1' }]; - mockFsUtil.readFile - .onFirstCall() - .returns(locales) - .onSecondCall() - .returns(contentTypes); + mockFsUtil.readFile.onFirstCall().returns(locales).onSecondCall().returns(contentTypes); const contentTypeStub = sandbox.stub().returns({ entry: sandbox.stub().returns({ query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: [], - count: 0 - }) - }) - }) + count: 0, + }), + }), + }), }); mockStackAPIClient.contentType = contentTypeStub; // Update entriesExport to use the new mock @@ -371,21 +361,17 @@ describe('EntriesExport', () => { const locales = [{ code: 'en-us' }]; const contentTypes = [{ uid: 'ct-1', title: 'Content Type 1' }]; - mockFsUtil.readFile - .onFirstCall() - .returns(locales) - .onSecondCall() - .returns(contentTypes); + mockFsUtil.readFile.onFirstCall().returns(locales).onSecondCall().returns(contentTypes); const contentTypeStub = sandbox.stub().returns({ entry: sandbox.stub().returns({ query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: [], - count: 0 - }) - }) - }) + count: 0, + }), + }), + }), }); mockStackAPIClient.contentType = contentTypeStub; // Update entriesExport to use the new mock @@ -408,13 +394,10 @@ describe('EntriesExport', () => { describe('createRequestObjects() method', () => { it('should create request objects for each content type and locale combination', () => { - const locales = [ - { code: 'en-us' }, - { code: 'fr-fr' } - ]; + const locales = [{ code: 'en-us' }, { code: 'fr-fr' }]; const contentTypes = [ { uid: 'ct-1', title: 'Content Type 1' }, - { uid: 'ct-2', title: 'Content Type 2' } + { uid: 'ct-2', title: 'Content Type 2' }, ]; const requestObjects = entriesExport.createRequestObjects(locales, contentTypes); @@ -424,19 +407,19 @@ describe('EntriesExport', () => { expect(requestObjects).to.have.length(6); expect(requestObjects).to.deep.include({ contentType: 'ct-1', - locale: 'en-us' + locale: 'en-us', }); expect(requestObjects).to.deep.include({ contentType: 'ct-1', - locale: 'fr-fr' + locale: 'fr-fr', }); expect(requestObjects).to.deep.include({ contentType: 'ct-1', - locale: mockExportConfig.master_locale.code + locale: mockExportConfig.master_locale.code, }); expect(requestObjects).to.deep.include({ contentType: 'ct-2', - locale: 'en-us' + locale: 'en-us', }); }); @@ -451,9 +434,7 @@ describe('EntriesExport', () => { it('should use master locale only when locales array is empty', () => { const locales: any[] = []; - const contentTypes = [ - { uid: 'ct-1', title: 'Content Type 1' } - ]; + const contentTypes = [{ uid: 'ct-1', title: 'Content Type 1' }]; const requestObjects = entriesExport.createRequestObjects(locales, contentTypes); @@ -461,15 +442,13 @@ describe('EntriesExport', () => { expect(requestObjects).to.have.length(1); expect(requestObjects[0]).to.deep.equal({ contentType: 'ct-1', - locale: mockExportConfig.master_locale.code + locale: mockExportConfig.master_locale.code, }); }); it('should use master locale only when locales is not an array', () => { const locales = {} as any; - const contentTypes = [ - { uid: 'ct-1', title: 'Content Type 1' } - ]; + const contentTypes = [{ uid: 'ct-1', title: 'Content Type 1' }]; const requestObjects = entriesExport.createRequestObjects(locales, contentTypes); @@ -487,7 +466,7 @@ describe('EntriesExport', () => { // Should have 2 objects: one for de-de and one for master locale expect(requestObjects).to.have.length(2); const masterLocaleObjects = requestObjects.filter( - (obj: any) => obj.locale === mockExportConfig.master_locale.code + (obj: any) => obj.locale === mockExportConfig.master_locale.code, ); expect(masterLocaleObjects).to.have.length(1); }); @@ -498,7 +477,7 @@ describe('EntriesExport', () => { const options = { contentType: 'ct-1', locale: 'en-us', - skip: 0 + skip: 0, }; const mockEntryQuery = { @@ -506,35 +485,29 @@ describe('EntriesExport', () => { find: sandbox.stub().resolves({ items: [ { uid: 'entry-1', title: 'Entry 1' }, - { uid: 'entry-2', title: 'Entry 2' } + { uid: 'entry-2', title: 'Entry 2' }, ], - count: 2 - }) - }) + count: 2, + }), + }), }; mockStackAPIClient.contentType.returns({ - entry: sandbox.stub().returns(mockEntryQuery) + entry: sandbox.stub().returns(mockEntryQuery), }); await entriesExport.getEntries(options); // Should create directory - const expectedPath = path.join( - entriesExport.entriesDirPath, - 'ct-1', - 'en-us' - ); + const expectedPath = path.join(entriesExport.entriesDirPath, 'ct-1', 'en-us'); expect(mockFsUtil.makeDirectory.called).to.be.true; expect(mockFsUtil.makeDirectory.calledWith(expectedPath)).to.be.true; // Should initialize FsUtility expect(entriesExport.entriesFileHelper).to.be.instanceOf(FsUtility); // Should write entries to file expect((FsUtility.prototype.writeIntoFile as sinon.SinonStub).called).to.be.true; - expect((FsUtility.prototype.writeIntoFile as sinon.SinonStub).calledWith( - sinon.match.array, - { mapKeyVal: true } - )).to.be.true; + expect((FsUtility.prototype.writeIntoFile as sinon.SinonStub).calledWith(sinon.match.array, { mapKeyVal: true })) + .to.be.true; // Should query with correct parameters expect(mockEntryQuery.query.called).to.be.true; }); @@ -543,7 +516,7 @@ describe('EntriesExport', () => { const options = { contentType: 'ct-1', locale: 'en-us', - skip: 0 + skip: 0, }; // Initialize FsUtility on first call @@ -553,20 +526,20 @@ describe('EntriesExport', () => { basePath: '/test/path', chunkFileSize: 1000, keepMetadata: false, - omitKeys: [] + omitKeys: [], }); const mockEntryQuery = { query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: [{ uid: 'entry-1' }], - count: 150 // More than limit, will paginate - }) - }) + count: 150, // More than limit, will paginate + }), + }), }; mockStackAPIClient.contentType.returns({ - entry: sandbox.stub().returns(mockEntryQuery) + entry: sandbox.stub().returns(mockEntryQuery), }); // First call @@ -585,7 +558,7 @@ describe('EntriesExport', () => { const options = { contentType: 'ct-1', locale: 'en-us', - skip: 0 + skip: 0, }; let callCount = 0; @@ -595,26 +568,32 @@ describe('EntriesExport', () => { callCount++; if (callCount === 1) { return Promise.resolve({ - items: Array(100).fill(null).map((_, i) => ({ uid: `entry-${i}` })), - count: 250 // Total entries + items: Array(100) + .fill(null) + .map((_, i) => ({ uid: `entry-${i}` })), + count: 250, // Total entries }); } else if (callCount === 2) { return Promise.resolve({ - items: Array(100).fill(null).map((_, i) => ({ uid: `entry-${100 + i}` })), - count: 250 + items: Array(100) + .fill(null) + .map((_, i) => ({ uid: `entry-${100 + i}` })), + count: 250, }); } else { return Promise.resolve({ - items: Array(50).fill(null).map((_, i) => ({ uid: `entry-${200 + i}` })), - count: 250 + items: Array(50) + .fill(null) + .map((_, i) => ({ uid: `entry-${200 + i}` })), + count: 250, }); } - }) - }) + }), + }), }; mockStackAPIClient.contentType.returns({ - entry: sandbox.stub().returns(mockEntryQuery) + entry: sandbox.stub().returns(mockEntryQuery), }); await entriesExport.getEntries(options); @@ -629,20 +608,20 @@ describe('EntriesExport', () => { const options = { contentType: 'ct-1', locale: 'en-us', - skip: 0 + skip: 0, }; const mockEntryQuery = { query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }; mockStackAPIClient.contentType.returns({ - entry: sandbox.stub().returns(mockEntryQuery) + entry: sandbox.stub().returns(mockEntryQuery), }); await entriesExport.getEntries(options); @@ -658,7 +637,7 @@ describe('EntriesExport', () => { const options = { contentType: 'ct-1', locale: 'en-us', - skip: 0 + skip: 0, }; const apiError = new Error('API Error'); @@ -673,12 +652,12 @@ describe('EntriesExport', () => { const mockEntryQuery = { query: sandbox.stub().returns({ - find: sandbox.stub().rejects(apiError) - }) + find: sandbox.stub().rejects(apiError), + }), }; mockStackAPIClient.contentType.returns({ - entry: sandbox.stub().returns(mockEntryQuery) + entry: sandbox.stub().returns(mockEntryQuery), }); try { @@ -688,13 +667,10 @@ describe('EntriesExport', () => { expect(error).to.equal(apiError); // Should handle and log error with context expect(handleAndLogErrorSpy.called).to.be.true; - expect(handleAndLogErrorSpy.calledWith( - apiError, - sinon.match.has('contentType', 'ct-1') - )).to.be.true; + expect(handleAndLogErrorSpy.calledWith(apiError, sinon.match.has('contentType', 'ct-1'))).to.be.true; expect(handleAndLogErrorSpy.getCall(0).args[1]).to.include({ locale: 'en-us', - contentType: 'ct-1' + contentType: 'ct-1', }); } }); @@ -706,7 +682,7 @@ describe('EntriesExport', () => { entriesExport = new EntriesExport({ exportConfig: mockExportConfig, stackAPIClient: mockStackAPIClient, - moduleName: 'entries' + moduleName: 'entries', }); }); @@ -714,25 +690,25 @@ describe('EntriesExport', () => { const options = { contentType: 'ct-1', locale: 'en-us', - skip: 0 + skip: 0, }; const entries = [ { uid: 'entry-1', _version: 3 }, - { uid: 'entry-2', _version: 2 } + { uid: 'entry-2', _version: 2 }, ]; const mockEntryQuery = { query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: entries, - count: 2 - }) - }) + count: 2, + }), + }), }; mockStackAPIClient.contentType.returns({ - entry: sandbox.stub().returns(mockEntryQuery) + entry: sandbox.stub().returns(mockEntryQuery), }); // Stub fetchEntriesVersions @@ -742,14 +718,16 @@ describe('EntriesExport', () => { // Should call fetchEntriesVersions with entries expect((entriesExport.fetchEntriesVersions as sinon.SinonStub).called).to.be.true; - expect((entriesExport.fetchEntriesVersions as sinon.SinonStub).calledWith( - entries, - sinon.match({ - locale: 'en-us', - contentType: 'ct-1', - versionedEntryPath: sinon.match.string - }) - )).to.be.true; + expect( + (entriesExport.fetchEntriesVersions as sinon.SinonStub).calledWith( + entries, + sinon.match({ + locale: 'en-us', + contentType: 'ct-1', + versionedEntryPath: sinon.match.string, + }), + ), + ).to.be.true; // Should create versions directory expect(mockFsUtil.makeDirectory.called).to.be.true; const makeDirCalls = mockFsUtil.makeDirectory.getCalls(); @@ -762,26 +740,26 @@ describe('EntriesExport', () => { entriesExport = new EntriesExport({ exportConfig: mockExportConfig, stackAPIClient: mockStackAPIClient, - moduleName: 'entries' + moduleName: 'entries', }); const options = { contentType: 'ct-1', locale: 'en-us', - skip: 0 + skip: 0, }; const mockEntryQuery = { query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: [{ uid: 'entry-1' }], - count: 1 - }) - }) + count: 1, + }), + }), }; mockStackAPIClient.contentType.returns({ - entry: sandbox.stub().returns(mockEntryQuery) + entry: sandbox.stub().returns(mockEntryQuery), }); sandbox.stub(entriesExport, 'fetchEntriesVersions').resolves(); @@ -801,36 +779,38 @@ describe('EntriesExport', () => { const options = { contentType: 'ct-1', locale: 'en-us', - skip: 0 + skip: 0, }; const entries = [ { uid: 'entry-1', title: 'Entry 1' }, - { uid: 'entry-2', title: 'Entry 2' } + { uid: 'entry-2', title: 'Entry 2' }, ]; const mockEntryQuery = { query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: entries, - count: 2 - }) - }) + count: 2, + }), + }), }; mockStackAPIClient.contentType.returns({ - entry: sandbox.stub().returns(mockEntryQuery) + entry: sandbox.stub().returns(mockEntryQuery), }); await entriesExport.getEntries(options); // Should call exportVariantEntry with correct parameters expect(mockVariantEntries.exportVariantEntry.called).to.be.true; - expect(mockVariantEntries.exportVariantEntry.calledWith({ - locale: 'en-us', - contentTypeUid: 'ct-1', - entries: entries - })).to.be.true; + expect( + mockVariantEntries.exportVariantEntry.calledWith({ + locale: 'en-us', + contentTypeUid: 'ct-1', + entries: entries, + }), + ).to.be.true; }); it('should not export variant entries when exportVariantEntry is disabled', async () => { @@ -839,20 +819,20 @@ describe('EntriesExport', () => { const options = { contentType: 'ct-1', locale: 'en-us', - skip: 0 + skip: 0, }; const mockEntryQuery = { query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: [{ uid: 'entry-1' }], - count: 1 - }) - }) + count: 1, + }), + }), }; mockStackAPIClient.contentType.returns({ - entry: sandbox.stub().returns(mockEntryQuery) + entry: sandbox.stub().returns(mockEntryQuery), }); await entriesExport.getEntries(options); @@ -868,12 +848,12 @@ describe('EntriesExport', () => { it('should process entries through makeConcurrentCall with correct configuration', async () => { const entries = [ { uid: 'entry-1', _version: 2 }, - { uid: 'entry-2', _version: 1 } + { uid: 'entry-2', _version: 1 }, ]; const options = { locale: 'en-us', contentType: 'ct-1', - versionedEntryPath: '/test/versions' + versionedEntryPath: '/test/versions', }; // Stub makeConcurrentCall @@ -904,33 +884,35 @@ describe('EntriesExport', () => { module: 'versioned-entries', queryParam: { locale: 'en-us', - contentType: 'ct-1' + contentType: 'ct-1', }, resolve: sandbox.spy(), - reject: sandbox.spy() + reject: sandbox.spy(), }; - const versions = [{ uid: 'entry-1', _version: 1 }, { uid: 'entry-1', _version: 2 }]; + const versions = [ + { uid: 'entry-1', _version: 1 }, + { uid: 'entry-1', _version: 2 }, + ]; sandbox.stub(entriesExport, 'getEntryByVersion').resolves(versions); await entriesExport.entryVersionHandler({ apiParams: apiParams as any, element: entry, - isLastRequest: false + isLastRequest: false, }); // Should call getEntryByVersion expect((entriesExport.getEntryByVersion as sinon.SinonStub).called).to.be.true; - expect((entriesExport.getEntryByVersion as sinon.SinonStub).calledWith( - apiParams.queryParam, - entry - )).to.be.true; + expect((entriesExport.getEntryByVersion as sinon.SinonStub).calledWith(apiParams.queryParam, entry)).to.be.true; // Should call resolve with correct data expect(apiParams.resolve.called).to.be.true; - expect(apiParams.resolve.calledWith({ - response: versions, - apiData: entry - })).to.be.true; + expect( + apiParams.resolve.calledWith({ + response: versions, + apiData: entry, + }), + ).to.be.true; // Should not call reject expect(apiParams.reject.called).to.be.false; }); @@ -941,10 +923,10 @@ describe('EntriesExport', () => { module: 'versioned-entries', queryParam: { locale: 'en-us', - contentType: 'ct-1' + contentType: 'ct-1', }, resolve: sandbox.spy(), - reject: sandbox.spy() + reject: sandbox.spy(), }; const versionError = new Error('Version fetch failed'); @@ -955,7 +937,7 @@ describe('EntriesExport', () => { await entriesExport.entryVersionHandler({ apiParams: apiParams as any, element: entry, - isLastRequest: false + isLastRequest: false, }); } catch (error) { // Expected - the handler rejects with true @@ -964,10 +946,12 @@ describe('EntriesExport', () => { // Should call reject with error expect(apiParams.reject.called).to.be.true; - expect(apiParams.reject.calledWith({ - error: versionError, - apiData: entry - })).to.be.true; + expect( + apiParams.reject.calledWith({ + error: versionError, + apiData: entry, + }), + ).to.be.true; // Should not call resolve expect(apiParams.resolve.called).to.be.false; }); @@ -978,7 +962,7 @@ describe('EntriesExport', () => { const entry = { uid: 'entry-1', _version: 3 }; const options = { locale: 'en-us', - contentType: 'ct-1' + contentType: 'ct-1', }; let versionCallCount = 0; @@ -986,15 +970,15 @@ describe('EntriesExport', () => { versionCallCount++; return Promise.resolve({ uid: 'entry-1', - _version: 4 - versionCallCount // 3, 2, 1 + _version: 4 - versionCallCount, // 3, 2, 1 }); }); const mockEntryMethod = sandbox.stub().callsFake((uid: string) => ({ - fetch: mockEntryFetch + fetch: mockEntryFetch, })); mockStackAPIClient.contentType.returns({ - entry: mockEntryMethod + entry: mockEntryMethod, }); const versions = await entriesExport.getEntryByVersion(options, entry); @@ -1005,7 +989,7 @@ describe('EntriesExport', () => { // Should fetch with correct version numbers expect(mockEntryFetch.getCall(0).args[0]).to.deep.include({ version: 3, - locale: 'en-us' + locale: 'en-us', }); }); @@ -1013,19 +997,19 @@ describe('EntriesExport', () => { const entry = { uid: 'entry-1', _version: 1 }; const options = { locale: 'en-us', - contentType: 'ct-1' + contentType: 'ct-1', }; const mockEntryFetch = sandbox.stub().resolves({ uid: 'entry-1', - _version: 1 + _version: 1, }); const mockEntryMethod = sandbox.stub().callsFake((uid: string) => ({ - fetch: mockEntryFetch + fetch: mockEntryFetch, })); mockStackAPIClient.contentType.returns({ - entry: mockEntryMethod + entry: mockEntryMethod, }); const versions = await entriesExport.getEntryByVersion(options, entry); @@ -1039,29 +1023,31 @@ describe('EntriesExport', () => { const entry = { uid: 'entry-1', _version: 1 }; const options = { locale: 'en-us', - contentType: 'ct-1' + contentType: 'ct-1', }; const mockEntryFetch = sandbox.stub().resolves({ uid: 'entry-1' }); const mockEntryMethod = sandbox.stub().callsFake((uid: string) => ({ - fetch: mockEntryFetch + fetch: mockEntryFetch, })); mockStackAPIClient.contentType.returns({ - entry: mockEntryMethod + entry: mockEntryMethod, }); await entriesExport.getEntryByVersion(options, entry); // Should include except.BASE with invalidKeys expect(mockEntryFetch.called).to.be.true; - expect(mockEntryFetch.calledWith( - sinon.match({ - except: { - BASE: mockExportConfig.modules.entries.invalidKeys - } - }) - )).to.be.true; + expect( + mockEntryFetch.calledWith( + sinon.match({ + except: { + BASE: mockExportConfig.modules.entries.invalidKeys, + }, + }), + ), + ).to.be.true; }); }); @@ -1070,26 +1056,22 @@ describe('EntriesExport', () => { const locales = [{ code: 'en-us' }]; const contentTypes = [ { uid: 'ct-1', title: 'Content Type 1' }, - { uid: 'ct-2', title: 'Content Type 2' } + { uid: 'ct-2', title: 'Content Type 2' }, ]; - mockFsUtil.readFile - .onFirstCall() - .returns(locales) - .onSecondCall() - .returns(contentTypes); + mockFsUtil.readFile.onFirstCall().returns(locales).onSecondCall().returns(contentTypes); const mockEntryQuery = { query: sandbox.stub().returns({ find: sandbox.stub().resolves({ items: [{ uid: 'entry-1' }], - count: 1 - }) - }) + count: 1, + }), + }), }; const contentTypeStub = sandbox.stub().returns({ - entry: sandbox.stub().returns(mockEntryQuery) + entry: sandbox.stub().returns(mockEntryQuery), }); mockStackAPIClient.contentType = contentTypeStub; // Update entriesExport to use the new mock @@ -1118,32 +1100,30 @@ describe('EntriesExport', () => { const locales = [{ code: 'en-us' }]; const contentTypes = [{ uid: 'ct-1', title: 'Content Type 1' }]; - mockFsUtil.readFile - .onFirstCall() - .returns(locales) - .onSecondCall() - .returns(contentTypes); + mockFsUtil.readFile.onFirstCall().returns(locales).onSecondCall().returns(contentTypes); const processingError = new Error('Entry processing failed'); const getEntriesStub = sandbox.stub(entriesExport, 'getEntries').rejects(processingError); - + // Stub getTotalEntriesCount to return > 0 so the loop executes sandbox.stub(entriesExport, 'getTotalEntriesCount').resolves(1); sandbox.stub(entriesExport, 'setupVariantExport').resolves(null); - + // Stub progress manager to avoid issues sandbox.stub(entriesExport as any, 'createNestedProgress').returns({ addProcess: sandbox.stub(), startProcess: sandbox.stub().returns({ - updateStatus: sandbox.stub() + updateStatus: sandbox.stub(), }), updateStatus: sandbox.stub(), completeProcess: sandbox.stub(), - tick: sandbox.stub() + tick: sandbox.stub(), } as any); - sandbox.stub(entriesExport as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sandbox + .stub(entriesExport as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); const completeProgressStub = sandbox.stub(entriesExport as any, 'completeProgress'); await entriesExport.start(); @@ -1156,4 +1136,3 @@ describe('EntriesExport', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/environments.test.ts b/packages/contentstack-export/test/unit/export/modules/environments.test.ts index da7949b00f..033c856e2e 100644 --- a/packages/contentstack-export/test/unit/export/modules/environments.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/environments.test.ts @@ -16,16 +16,15 @@ describe('ExportEnvironments', () => { find: sinon.stub().resolves({ items: [ { uid: 'env-1', name: 'Production' }, - { uid: 'env-2', name: 'Development' } + { uid: 'env-2', name: 'Development' }, ], - count: 2 - }) - }) - }) + count: 2, + }), + }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -41,7 +40,7 @@ describe('ExportEnvironments', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -50,7 +49,7 @@ describe('ExportEnvironments', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -62,22 +61,21 @@ describe('ExportEnvironments', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['environments'], environments: { dirName: 'environments', fileName: 'environments.json', limit: 100, - invalidKeys: [] - } - } + invalidKeys: [], + }, + }, } as any; exportEnvironments = new ExportEnvironments({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'environments' + moduleName: 'environments', }); sinon.stub(FsUtility.prototype, 'writeFile').resolves(); @@ -106,20 +104,20 @@ describe('ExportEnvironments', () => { it('should fetch and process environments correctly', async () => { const environments = [ { uid: 'env-1', name: 'Production', ACL: 'test' }, - { uid: 'env-2', name: 'Development', ACL: 'test' } + { uid: 'env-2', name: 'Development', ACL: 'test' }, ]; mockStackClient.environment.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: environments, - count: 2 - }) - }) + count: 2, + }), + }), }); await exportEnvironments.getEnvironments(); - + // Verify environments were processed expect(Object.keys(exportEnvironments.environments).length).to.equal(2); expect(exportEnvironments.environments['env-1']).to.exist; @@ -137,20 +135,20 @@ describe('ExportEnvironments', () => { if (callCount === 1) { return Promise.resolve({ items: Array(100).fill({ uid: 'test', name: 'Test' }), - count: 150 + count: 150, }); } else { return Promise.resolve({ items: Array(50).fill({ uid: 'test2', name: 'Test2' }), - count: 150 + count: 150, }); } - }) - }) + }), + }), }); await exportEnvironments.getEnvironments(); - + // Verify multiple calls were made for recursive fetching expect(callCount).to.be.greaterThan(1); }); @@ -158,12 +156,12 @@ describe('ExportEnvironments', () => { it('should handle API errors gracefully', async () => { mockStackClient.environment.returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(new Error('API Error')) - }) + find: sinon.stub().rejects(new Error('API Error')), + }), }); await exportEnvironments.getEnvironments(); - + // Verify method completes without throwing expect(exportEnvironments.environments).to.exist; }); @@ -173,14 +171,14 @@ describe('ExportEnvironments', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = Object.keys(exportEnvironments.environments).length; await exportEnvironments.getEnvironments(); - + // Verify no new environments were added expect(Object.keys(exportEnvironments.environments).length).to.equal(initialCount); }); @@ -190,14 +188,14 @@ describe('ExportEnvironments', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: null, - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = Object.keys(exportEnvironments.environments).length; await exportEnvironments.getEnvironments(); - + // Verify no processing occurred with null items expect(Object.keys(exportEnvironments.environments).length).to.equal(initialCount); }); @@ -206,23 +204,23 @@ describe('ExportEnvironments', () => { describe('start() method', () => { it('should complete full export flow and write files', async () => { const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; - + const environments = [ { uid: 'env-1', name: 'Production' }, - { uid: 'env-2', name: 'Development' } + { uid: 'env-2', name: 'Development' }, ]; mockStackClient.environment.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: environments, - count: 2 - }) - }) + count: 2, + }), + }), }); await exportEnvironments.start(); - + // Verify environments were processed expect(Object.keys(exportEnvironments.environments).length).to.equal(2); expect(exportEnvironments.environments['env-1']).to.exist; @@ -238,14 +236,14 @@ describe('ExportEnvironments', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); exportEnvironments.environments = {}; await exportEnvironments.start(); - + // Verify writeFile was NOT called when environments are empty expect(writeFileStub.called).to.be.false; }); @@ -255,7 +253,7 @@ describe('ExportEnvironments', () => { it('should sanitize environment attributes and remove ACL', () => { const environments = [ { uid: 'env-1', name: 'Production', ACL: 'remove' }, - { uid: 'env-2', name: 'Development', ACL: 'remove' } + { uid: 'env-2', name: 'Development', ACL: 'remove' }, ]; exportEnvironments.sanitizeAttribs(environments); @@ -265,9 +263,7 @@ describe('ExportEnvironments', () => { }); it('should handle environments without name field', () => { - const environments = [ - { uid: 'env-1', ACL: 'remove' } - ]; + const environments = [{ uid: 'env-1', ACL: 'remove' }]; exportEnvironments.sanitizeAttribs(environments); @@ -284,4 +280,3 @@ describe('ExportEnvironments', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/extensions.test.ts b/packages/contentstack-export/test/unit/export/modules/extensions.test.ts index 714e1954bc..0989ab2e39 100644 --- a/packages/contentstack-export/test/unit/export/modules/extensions.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/extensions.test.ts @@ -16,16 +16,15 @@ describe('ExportExtensions', () => { find: sinon.stub().resolves({ items: [ { uid: 'ext-1', title: 'Extension 1' }, - { uid: 'ext-2', title: 'Extension 2' } + { uid: 'ext-2', title: 'Extension 2' }, ], - count: 2 - }) - }) - }) + count: 2, + }), + }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -41,7 +40,7 @@ describe('ExportExtensions', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -50,7 +49,7 @@ describe('ExportExtensions', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -62,22 +61,21 @@ describe('ExportExtensions', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['extensions'], extensions: { dirName: 'extensions', fileName: 'extensions.json', limit: 100, - invalidKeys: [] - } - } + invalidKeys: [], + }, + }, } as any; exportExtensions = new ExportExtensions({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'extensions' + moduleName: 'extensions', }); sinon.stub(FsUtility.prototype, 'writeFile').resolves(); @@ -106,20 +104,20 @@ describe('ExportExtensions', () => { it('should fetch and process extensions correctly', async () => { const extensions = [ { uid: 'ext-1', title: 'Extension 1', SYS_ACL: 'test' }, - { uid: 'ext-2', title: 'Extension 2', SYS_ACL: 'test' } + { uid: 'ext-2', title: 'Extension 2', SYS_ACL: 'test' }, ]; mockStackClient.extension.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: extensions, - count: 2 - }) - }) + count: 2, + }), + }), }); await exportExtensions.getExtensions(); - + // Verify extensions were processed expect(Object.keys(exportExtensions.extensions).length).to.equal(2); expect(exportExtensions.extensions['ext-1']).to.exist; @@ -137,20 +135,20 @@ describe('ExportExtensions', () => { if (callCount === 1) { return Promise.resolve({ items: Array(100).fill({ uid: 'test', title: 'Test' }), - count: 150 + count: 150, }); } else { return Promise.resolve({ items: Array(50).fill({ uid: 'test2', title: 'Test2' }), - count: 150 + count: 150, }); } - }) - }) + }), + }), }); await exportExtensions.getExtensions(); - + // Verify multiple calls were made for recursive fetching expect(callCount).to.be.greaterThan(1); }); @@ -158,12 +156,12 @@ describe('ExportExtensions', () => { it('should handle API errors gracefully', async () => { mockStackClient.extension.returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(new Error('API Error')) - }) + find: sinon.stub().rejects(new Error('API Error')), + }), }); await exportExtensions.getExtensions(); - + // Verify method completes without throwing expect(exportExtensions.extensions).to.exist; }); @@ -173,14 +171,14 @@ describe('ExportExtensions', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = Object.keys(exportExtensions.extensions).length; await exportExtensions.getExtensions(); - + // Verify no new extensions were added expect(Object.keys(exportExtensions.extensions).length).to.equal(initialCount); }); @@ -190,14 +188,14 @@ describe('ExportExtensions', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: null, - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = Object.keys(exportExtensions.extensions).length; await exportExtensions.getExtensions(); - + // Verify no processing occurred with null items expect(Object.keys(exportExtensions.extensions).length).to.equal(initialCount); }); @@ -206,23 +204,23 @@ describe('ExportExtensions', () => { describe('start() method', () => { it('should complete full export flow and write files', async () => { const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; - + const extensions = [ { uid: 'ext-1', title: 'Extension 1' }, - { uid: 'ext-2', title: 'Extension 2' } + { uid: 'ext-2', title: 'Extension 2' }, ]; mockStackClient.extension.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: extensions, - count: 2 - }) - }) + count: 2, + }), + }), }); await exportExtensions.start(); - + // Verify extensions were processed expect(Object.keys(exportExtensions.extensions).length).to.equal(2); expect(exportExtensions.extensions['ext-1']).to.exist; @@ -238,14 +236,14 @@ describe('ExportExtensions', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); exportExtensions.extensions = {}; await exportExtensions.start(); - + // Verify writeFile was NOT called when extensions are empty expect(writeFileStub.called).to.be.false; }); @@ -255,7 +253,7 @@ describe('ExportExtensions', () => { it('should sanitize extension attributes and remove SYS_ACL', () => { const extensions = [ { uid: 'ext-1', title: 'Extension 1', SYS_ACL: 'remove' }, - { uid: 'ext-2', title: 'Extension 2', SYS_ACL: 'remove' } + { uid: 'ext-2', title: 'Extension 2', SYS_ACL: 'remove' }, ]; exportExtensions.sanitizeAttribs(extensions); @@ -265,9 +263,7 @@ describe('ExportExtensions', () => { }); it('should handle extensions without title field', () => { - const extensions = [ - { uid: 'ext-1', SYS_ACL: 'remove' } - ]; + const extensions = [{ uid: 'ext-1', SYS_ACL: 'remove' }]; exportExtensions.sanitizeAttribs(extensions); @@ -284,4 +280,3 @@ describe('ExportExtensions', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/global-fields.test.ts b/packages/contentstack-export/test/unit/export/modules/global-fields.test.ts index 35860daaf0..4f8c853d68 100644 --- a/packages/contentstack-export/test/unit/export/modules/global-fields.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/global-fields.test.ts @@ -16,16 +16,15 @@ describe('ExportGlobalFields', () => { find: sinon.stub().resolves({ items: [ { uid: 'gf-1', title: 'Global Field 1', validKey: 'value1' }, - { uid: 'gf-2', title: 'Global Field 2', validKey: 'value2', invalidKey: 'remove' } + { uid: 'gf-2', title: 'Global Field 2', validKey: 'value2', invalidKey: 'remove' }, ], - count: 2 - }) - }) - }) + count: 2, + }), + }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -41,7 +40,7 @@ describe('ExportGlobalFields', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -50,7 +49,7 @@ describe('ExportGlobalFields', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -62,7 +61,6 @@ describe('ExportGlobalFields', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['global-fields'], 'global-fields': { @@ -71,15 +69,15 @@ describe('ExportGlobalFields', () => { validKeys: ['uid', 'title', 'validKey'], fetchConcurrency: 5, writeConcurrency: 5, - limit: 100 - } - } + limit: 100, + }, + }, } as any; exportGlobalFields = new ExportGlobalFields({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'global-fields' + moduleName: 'global-fields', }); // Stub FsUtility methods @@ -110,7 +108,7 @@ describe('ExportGlobalFields', () => { expect(exportGlobalFields.qs).to.deep.include({ include_count: true, asc: 'updated_at', - include_global_field_schema: true + include_global_field_schema: true, }); }); @@ -128,16 +126,16 @@ describe('ExportGlobalFields', () => { it('should fetch and process global fields correctly', async () => { const globalFields = [ { uid: 'gf-1', title: 'Field 1', validKey: 'value1', invalidKey: 'remove' }, - { uid: 'gf-2', title: 'Field 2', validKey: 'value2', invalidKey: 'remove' } + { uid: 'gf-2', title: 'Field 2', validKey: 'value2', invalidKey: 'remove' }, ]; mockStackClient.globalField.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: globalFields, - count: 2 - }) - }) + count: 2, + }), + }), }); await exportGlobalFields.getGlobalFields(); @@ -159,16 +157,16 @@ describe('ExportGlobalFields', () => { if (callCount === 1) { return Promise.resolve({ items: new Array(100).fill({ uid: 'test', title: 'Test', validKey: 'value' }), - count: 150 + count: 150, }); } else { return Promise.resolve({ items: new Array(50).fill({ uid: 'test2', title: 'Test2', validKey: 'value' }), - count: 150 + count: 150, }); } - }) - }) + }), + }), }); await exportGlobalFields.getGlobalFields(); @@ -181,8 +179,8 @@ describe('ExportGlobalFields', () => { it('should handle API errors gracefully', async () => { mockStackClient.globalField.returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(new Error('API Error')) - }) + find: sinon.stub().rejects(new Error('API Error')), + }), }); try { @@ -198,9 +196,9 @@ describe('ExportGlobalFields', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = exportGlobalFields.globalFields.length; @@ -215,9 +213,9 @@ describe('ExportGlobalFields', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: null, - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = exportGlobalFields.globalFields.length; @@ -232,11 +230,11 @@ describe('ExportGlobalFields', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [{ uid: 'gf-1', title: 'Test', validKey: 'value' }], - count: 1 - }) - }) + count: 1, + }), + }), }); - + await exportGlobalFields.getGlobalFields(50); // Verify skip was set in query @@ -248,7 +246,7 @@ describe('ExportGlobalFields', () => { it('should sanitize global field attributes and remove invalid keys', () => { const globalFields = [ { uid: 'gf-1', title: 'Field 1', validKey: 'value1', invalidKey: 'remove' }, - { uid: 'gf-2', title: 'Field 2', validKey: 'value2', invalidKey: 'remove' } + { uid: 'gf-2', title: 'Field 2', validKey: 'value2', invalidKey: 'remove' }, ]; exportGlobalFields.sanitizeAttribs(globalFields); @@ -261,9 +259,7 @@ describe('ExportGlobalFields', () => { }); it('should handle global fields without required keys', () => { - const globalFields = [ - { uid: 'gf-1', invalidKey: 'remove' } - ]; + const globalFields = [{ uid: 'gf-1', invalidKey: 'remove' }]; exportGlobalFields.sanitizeAttribs(globalFields); @@ -281,20 +277,20 @@ describe('ExportGlobalFields', () => { it('should keep only valid keys from validKeys config', () => { const globalFields = [ - { - uid: 'gf-1', - title: 'Field 1', + { + uid: 'gf-1', + title: 'Field 1', validKey: 'value1', keyToRemove1: 'remove', keyToRemove2: 'remove', - keyToRemove3: 'remove' - } + keyToRemove3: 'remove', + }, ]; exportGlobalFields.sanitizeAttribs(globalFields); const processedField = exportGlobalFields.globalFields[0]; - + // Should only keep uid, title, validKey expect(processedField.keyToRemove1).to.be.undefined; expect(processedField.keyToRemove2).to.be.undefined; @@ -312,16 +308,16 @@ describe('ExportGlobalFields', () => { const globalFields = [ { uid: 'gf-1', title: 'Field 1', validKey: 'value1' }, - { uid: 'gf-2', title: 'Field 2', validKey: 'value2' } + { uid: 'gf-2', title: 'Field 2', validKey: 'value2' }, ]; mockStackClient.globalField.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: globalFields, - count: 2 - }) - }) + count: 2, + }), + }), }); await exportGlobalFields.start(); @@ -342,9 +338,9 @@ describe('ExportGlobalFields', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); exportGlobalFields.globalFields = []; @@ -358,8 +354,8 @@ describe('ExportGlobalFields', () => { it('should handle errors during export without throwing', async () => { mockStackClient.globalField.returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(new Error('Export failed')) - }) + find: sinon.stub().rejects(new Error('Export failed')), + }), }); // Should complete without throwing @@ -376,23 +372,27 @@ describe('ExportGlobalFields', () => { if (callCount === 1) { return Promise.resolve({ items: [], - count: 150 + count: 150, }); } else if (callCount === 2) { // Second call fetches first batch return Promise.resolve({ - items: new Array(100).fill(null).map((_, i) => ({ uid: `gf-${i + 1}`, title: 'Test', validKey: 'value' })), - count: 150 + items: new Array(100) + .fill(null) + .map((_, i) => ({ uid: `gf-${i + 1}`, title: 'Test', validKey: 'value' })), + count: 150, }); } else { // Third call fetches remaining batch return Promise.resolve({ - items: new Array(50).fill(null).map((_, i) => ({ uid: `gf-${i + 101}`, title: 'Test', validKey: 'value' })), - count: 150 + items: new Array(50) + .fill(null) + .map((_, i) => ({ uid: `gf-${i + 101}`, title: 'Test', validKey: 'value' })), + count: 150, }); } - }) - }) + }), + }), }; mockStackClient.globalField.returns(globalFieldMock); @@ -411,9 +411,9 @@ describe('ExportGlobalFields', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [{ uid: 'gf-1', title: 'Test', validKey: 'value' }], - count: 1 - }) - }) + count: 1, + }), + }), }); await exportGlobalFields.start(); @@ -424,4 +424,3 @@ describe('ExportGlobalFields', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/labels.test.ts b/packages/contentstack-export/test/unit/export/modules/labels.test.ts index af4bce1066..7e1b86a33b 100644 --- a/packages/contentstack-export/test/unit/export/modules/labels.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/labels.test.ts @@ -16,16 +16,15 @@ describe('ExportLabels', () => { find: sinon.stub().resolves({ items: [ { uid: 'label-1', name: 'Test Label 1', parent: [] }, - { uid: 'label-2', name: 'Test Label 2', parent: ['label-1'] } + { uid: 'label-2', name: 'Test Label 2', parent: ['label-1'] }, ], - count: 2 - }) - }) - }) + count: 2, + }), + }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -41,7 +40,7 @@ describe('ExportLabels', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -50,7 +49,7 @@ describe('ExportLabels', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -67,7 +66,7 @@ describe('ExportLabels', () => { users: '', extension: '', webhooks: '', - stacks: '' + stacks: '', }, preserveStackVersion: false, personalizationEnabled: false, @@ -75,22 +74,21 @@ describe('ExportLabels', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['labels'], labels: { dirName: 'labels', fileName: 'labels.json', invalidKeys: ['ACL', '_version'], - limit: 100 - } - } + limit: 100, + }, + }, } as any; exportLabels = new ExportLabels({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'labels' + moduleName: 'labels', }); // Stub FsUtility methods @@ -131,10 +129,10 @@ describe('ExportLabels', () => { describe('getLabels() method', () => { it('should fetch and process labels correctly', async () => { exportLabels.labels = {}; - + const labels = [ { uid: 'label-1', name: 'Test Label 1', parent: [] }, - { uid: 'label-2', name: 'Test Label 2', parent: ['label-1'] } + { uid: 'label-2', name: 'Test Label 2', parent: ['label-1'] }, ]; exportLabels.client = { @@ -142,14 +140,14 @@ describe('ExportLabels', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: labels, - count: 2 - }) - }) - }) + count: 2, + }), + }), + }), }; await exportLabels.getLabels(); - + // Verify labels were processed expect(Object.keys(exportLabels.labels).length).to.equal(2); expect(exportLabels.labels['label-1']).to.exist; @@ -165,20 +163,20 @@ describe('ExportLabels', () => { if (callCount === 1) { return Promise.resolve({ items: Array(100).fill({ uid: `label-${callCount}`, name: 'Test Label' }), - count: 150 + count: 150, }); } else { return Promise.resolve({ items: Array(50).fill({ uid: `label-${callCount}`, name: 'Test Label' }), - count: 150 + count: 150, }); } - }) - }) + }), + }), }); await exportLabels.getLabels(); - + // Verify multiple calls were made for recursive fetching expect(callCount).to.be.greaterThan(1); }); @@ -191,14 +189,14 @@ describe('ExportLabels', () => { return { find: sinon.stub().resolves({ items: [], - count: 0 - }) + count: 0, + }), }; - }) + }), }); await exportLabels.getLabels(50); - + // Verify skip was set in query params expect(queryParams.length).to.be.greaterThan(0); expect(queryParams[0].skip).to.equal(50); @@ -208,7 +206,7 @@ describe('ExportLabels', () => { exportLabels.labelConfig.limit = 50; let skipValues: number[] = []; let callCount = 0; - + mockStackClient.label.returns({ query: sinon.stub().returns({ find: sinon.stub().callsFake(() => { @@ -217,21 +215,21 @@ describe('ExportLabels', () => { skipValues.push(0); return Promise.resolve({ items: Array(50).fill({ uid: 'test', name: 'Test' }), - count: 100 + count: 100, }); } else { skipValues.push(50); return Promise.resolve({ items: [], - count: 100 + count: 100, }); } - }) - }) + }), + }), }); await exportLabels.getLabels(); - + // Verify skip was incremented by limit (50) expect(skipValues).to.include(50); }); @@ -240,7 +238,7 @@ describe('ExportLabels', () => { exportLabels.labelConfig.limit = undefined; let skipValues: number[] = []; let callCount = 0; - + mockStackClient.label.returns({ query: sinon.stub().returns({ find: sinon.stub().callsFake(() => { @@ -249,21 +247,21 @@ describe('ExportLabels', () => { skipValues.push(0); return Promise.resolve({ items: Array(100).fill({ uid: 'test', name: 'Test' }), - count: 200 + count: 200, }); } else { skipValues.push(100); return Promise.resolve({ items: [], - count: 200 + count: 200, }); } - }) - }) + }), + }), }); await exportLabels.getLabels(); - + // Verify skip was incremented by default limit (100) expect(skipValues).to.include(100); }); @@ -276,14 +274,14 @@ describe('ExportLabels', () => { callCount++; return Promise.resolve({ items: Array(50).fill({ uid: 'test', name: 'Test' }), - count: 50 + count: 50, }); - }) - }) + }), + }), }); await exportLabels.getLabels(); - + // Should only be called once since skip (100) >= count (50) after first call expect(callCount).to.equal(1); }); @@ -291,13 +289,13 @@ describe('ExportLabels', () => { it('should handle API errors gracefully', async () => { mockStackClient.label.returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(new Error('API Error')) - }) + find: sinon.stub().rejects(new Error('API Error')), + }), }); // The method should complete without throwing (error is caught and handled) await exportLabels.getLabels(); - + // Verify method completed - labels should still exist (initialized in constructor) expect(exportLabels.labels).to.exist; }); @@ -307,14 +305,14 @@ describe('ExportLabels', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = Object.keys(exportLabels.labels).length; await exportLabels.getLabels(); - + // Verify no new labels were added expect(Object.keys(exportLabels.labels).length).to.equal(initialCount); }); @@ -324,14 +322,14 @@ describe('ExportLabels', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: null, - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = Object.keys(exportLabels.labels).length; await exportLabels.getLabels(); - + // Verify no processing occurred with null items expect(Object.keys(exportLabels.labels).length).to.equal(initialCount); }); @@ -341,14 +339,14 @@ describe('ExportLabels', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: undefined, - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = Object.keys(exportLabels.labels).length; await exportLabels.getLabels(); - + // Verify no processing occurred with undefined items expect(Object.keys(exportLabels.labels).length).to.equal(initialCount); }); @@ -358,10 +356,10 @@ describe('ExportLabels', () => { it('should complete full export flow and write files', async () => { const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; const makeDirectoryStub = FsUtility.prototype.makeDirectory as sinon.SinonStub; - + const labels = [ { uid: 'label-1', name: 'Test Label 1', parent: [] }, - { uid: 'label-2', name: 'Test Label 2', parent: ['label-1'] } + { uid: 'label-2', name: 'Test Label 2', parent: ['label-1'] }, ]; exportLabels.client = { @@ -369,14 +367,14 @@ describe('ExportLabels', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: labels, - count: 2 - }) - }) - }) + count: 2, + }), + }), + }), }; await exportLabels.start(); - + // Verify directory was created expect(makeDirectoryStub.called).to.be.true; // Verify labels were processed @@ -397,15 +395,15 @@ describe('ExportLabels', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) - }) + count: 0, + }), + }), + }), }; exportLabels.labels = {}; await exportLabels.start(); - + // Verify writeFile was NOT called when labels are empty // isEmpty({}) returns true, so writeFile should not be called expect(writeFileStub.called).to.be.false; @@ -416,10 +414,10 @@ describe('ExportLabels', () => { // the code will throw when trying to call Object.keys on undefined // In practice, labels is always initialized in constructor, so this shouldn't happen exportLabels.labels = undefined as any; - + // Mock getLabels to not modify labels const getLabelsStub = sinon.stub(exportLabels, 'getLabels').resolves(); - + try { await exportLabels.start(); // If we get here, the code might have been fixed to handle undefined @@ -429,7 +427,7 @@ describe('ExportLabels', () => { // Object.keys will throw on undefined expect(error).to.exist; } - + getLabelsStub.restore(); }); @@ -438,17 +436,15 @@ describe('ExportLabels', () => { label: sinon.stub().returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ - items: [ - { uid: 'label-1', name: 'Test Label 1', parent: [] } - ], - count: 1 - }) - }) - }) + items: [{ uid: 'label-1', name: 'Test Label 1', parent: [] }], + count: 1, + }), + }), + }), }; await exportLabels.start(); - + // Verify labelsFolderPath was set expect(exportLabels.labelsFolderPath).to.exist; expect(exportLabels.labelsFolderPath).to.include('labels'); @@ -459,46 +455,42 @@ describe('ExportLabels', () => { exportLabels = new ExportLabels({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'labels' + moduleName: 'labels', }); exportLabels.client = { label: sinon.stub().returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ - items: [ - { uid: 'label-1', name: 'Test Label 1', parent: [] } - ], - count: 1 - }) - }) - }) + items: [{ uid: 'label-1', name: 'Test Label 1', parent: [] }], + count: 1, + }), + }), + }), }; await exportLabels.start(); - + // Verify branchName is included in path expect(exportLabels.labelsFolderPath).to.include('test-branch'); }); it('should write file with correct path and data', async () => { const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; - + exportLabels.client = { label: sinon.stub().returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ - items: [ - { uid: 'label-1', name: 'Test Label 1', parent: [] } - ], - count: 1 - }) - }) - }) + items: [{ uid: 'label-1', name: 'Test Label 1', parent: [] }], + count: 1, + }), + }), + }), }; await exportLabels.start(); - + // Verify writeFile was called with correct arguments expect(writeFileStub.called).to.be.true; const writeFileArgs = writeFileStub.firstCall.args; @@ -510,10 +502,10 @@ describe('ExportLabels', () => { describe('sanitizeAttribs() method', () => { it('should sanitize label attributes and remove invalid keys', () => { exportLabels.labels = {}; - + const labels = [ { uid: 'label-1', name: 'Test Label 1', ACL: 'remove', _version: 'remove', parent: [] }, - { uid: 'label-2', name: 'Test Label 2', ACL: 'remove', _version: 'remove', parent: ['label-1'] } + { uid: 'label-2', name: 'Test Label 2', ACL: 'remove', _version: 'remove', parent: ['label-1'] }, ]; exportLabels.sanitizeAttribs(labels); @@ -528,10 +520,8 @@ describe('ExportLabels', () => { it('should handle labels without name field', () => { exportLabels.labels = {}; - - const labels = [ - { uid: 'label-1', ACL: 'remove' } - ]; + + const labels = [{ uid: 'label-1', ACL: 'remove' }]; exportLabels.sanitizeAttribs(labels); @@ -541,7 +531,7 @@ describe('ExportLabels', () => { it('should handle empty labels array', () => { exportLabels.labels = {}; - + const labels: any[] = []; exportLabels.sanitizeAttribs(labels); @@ -551,10 +541,10 @@ describe('ExportLabels', () => { it('should handle labels with null or undefined values', () => { exportLabels.labels = {}; - + const labels = [ { uid: 'label-1', name: null as any, parent: [] as any[] }, - { uid: 'label-2', name: undefined as any, parent: [] as any[] } + { uid: 'label-2', name: undefined as any, parent: [] as any[] }, ]; exportLabels.sanitizeAttribs(labels); @@ -565,16 +555,16 @@ describe('ExportLabels', () => { it('should preserve valid keys after sanitization', () => { exportLabels.labels = {}; - + const labels = [ - { - uid: 'label-1', - name: 'Test Label', + { + uid: 'label-1', + name: 'Test Label', parent: ['parent-1'], color: '#FF0000', ACL: 'remove', - _version: 'remove' - } + _version: 'remove', + }, ]; exportLabels.sanitizeAttribs(labels); @@ -590,7 +580,7 @@ describe('ExportLabels', () => { it('should handle labels array with undefined length', () => { exportLabels.labels = {}; - + const labels: any = { length: undefined }; // This should not throw an error @@ -598,4 +588,3 @@ describe('ExportLabels', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/locales.test.ts b/packages/contentstack-export/test/unit/export/modules/locales.test.ts index 5f76a2cd10..da4dddc0f3 100644 --- a/packages/contentstack-export/test/unit/export/modules/locales.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/locales.test.ts @@ -14,17 +14,14 @@ describe('ExportLocales', () => { locale: sinon.stub().returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ - items: [ - { uid: 'locale-1', code: 'en-us', name: 'English (US)', fallback_locale: null } - ], - count: 1 - }) - }) - }) + items: [{ uid: 'locale-1', code: 'en-us', name: 'English (US)', fallback_locale: null }], + count: 1, + }), + }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -40,7 +37,7 @@ describe('ExportLocales', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -49,7 +46,7 @@ describe('ExportLocales', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -66,7 +63,7 @@ describe('ExportLocales', () => { users: '', extension: '', webhooks: '', - stacks: '' + stacks: '', }, preserveStackVersion: false, personalizationEnabled: false, @@ -74,26 +71,25 @@ describe('ExportLocales', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['locales'], locales: { dirName: 'locales', fileName: 'locales.json', - requiredKeys: ['code', 'name'] + requiredKeys: ['code', 'name'], }, masterLocale: { dirName: 'master_locale', fileName: 'master_locale.json', - requiredKeys: ['code'] - } - } + requiredKeys: ['code'], + }, + }, } as any; exportLocales = new ExportLocales({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'locales' + moduleName: 'locales', }); // Stub FsUtility methods @@ -129,10 +125,10 @@ describe('ExportLocales', () => { exportLocales.locales = {}; exportLocales.masterLocale = {}; exportLocales.exportConfig.master_locale = { code: 'en-us' }; - + const locales = [ { uid: 'locale-1', code: 'en-us', name: 'English' }, - { uid: 'locale-2', code: 'es-es', name: 'Spanish' } + { uid: 'locale-2', code: 'es-es', name: 'Spanish' }, ]; exportLocales.stackAPIClient = { @@ -140,14 +136,14 @@ describe('ExportLocales', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: locales, - count: 2 - }) - }) - }) + count: 2, + }), + }), + }), }; await exportLocales.getLocales(); - + // Verify locales were processed expect(Object.keys(exportLocales.locales).length).to.be.greaterThan(0); expect(Object.keys(exportLocales.masterLocale).length).to.be.greaterThan(0); @@ -162,20 +158,20 @@ describe('ExportLocales', () => { if (callCount === 1) { return Promise.resolve({ items: Array(100).fill({ uid: `locale-${callCount}`, code: 'en' }), - count: 150 + count: 150, }); } else { return Promise.resolve({ items: Array(50).fill({ uid: `locale-${callCount}`, code: 'en' }), - count: 150 + count: 150, }); } - }) - }) + }), + }), }); await exportLocales.getLocales(); - + // Verify multiple calls were made expect(callCount).to.be.greaterThan(1); }); @@ -183,8 +179,8 @@ describe('ExportLocales', () => { it('should handle API errors and throw', async () => { mockStackClient.locale.returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(new Error('API Error')) - }) + find: sinon.stub().rejects(new Error('API Error')), + }), }); try { @@ -200,23 +196,23 @@ describe('ExportLocales', () => { describe('start() method', () => { it('should complete full export flow and write files', async () => { exportLocales.exportConfig.master_locale = { code: 'en-us' }; - + exportLocales.stackAPIClient = { locale: sinon.stub().returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [ { uid: 'locale-1', code: 'en-us', name: 'English' }, - { uid: 'locale-2', code: 'es-es', name: 'Spanish' } + { uid: 'locale-2', code: 'es-es', name: 'Spanish' }, ], - count: 2 - }) - }) - }) + count: 2, + }), + }), + }), }; await exportLocales.start(); - + // Verify locales were fetched and processed expect(Object.keys(exportLocales.locales).length).to.be.greaterThan(0); // Verify writeFile was called (stub created in beforeEach) @@ -228,15 +224,15 @@ describe('ExportLocales', () => { exportLocales.stackAPIClient = { locale: sinon.stub().returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(new Error('API Error')) - }) - }) + find: sinon.stub().rejects(new Error('API Error')), + }), + }), }; try { await exportLocales.start(); expect.fail('Should have thrown an error'); - } catch (error:any) { + } catch (error: any) { expect(error).to.exist; expect(error.message).to.include('API Error'); } @@ -249,13 +245,13 @@ describe('ExportLocales', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); await exportLocales.getLocales(); - + expect(mockStackClient.locale.called).to.be.true; }); @@ -264,13 +260,13 @@ describe('ExportLocales', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: null, - count: 0 - }) - }) + count: 0, + }), + }), }); await exportLocales.getLocales(); - + expect(mockStackClient.locale.called).to.be.true; }); }); @@ -279,10 +275,10 @@ describe('ExportLocales', () => { it('should sanitize locale attributes', () => { exportLocales.locales = {}; exportLocales.masterLocale = {}; - + const locales = [ { uid: 'locale-1', code: 'en-us', name: 'English', extraField: 'remove' }, - { uid: 'locale-2', code: 'es-es', name: 'Spanish', extraField: 'remove' } + { uid: 'locale-2', code: 'es-es', name: 'Spanish', extraField: 'remove' }, ]; exportLocales.sanitizeAttribs(locales); @@ -294,10 +290,10 @@ describe('ExportLocales', () => { exportLocales.locales = {}; exportLocales.masterLocale = {}; exportLocales.exportConfig.master_locale = { code: 'en-us' }; - + const locales = [ { uid: 'locale-1', code: 'en-us', name: 'English' }, - { uid: 'locale-2', code: 'es-es', name: 'Spanish' } + { uid: 'locale-2', code: 'es-es', name: 'Spanish' }, ]; exportLocales.sanitizeAttribs(locales); @@ -311,7 +307,7 @@ describe('ExportLocales', () => { it('should handle empty locales array', () => { exportLocales.locales = {}; exportLocales.masterLocale = {}; - + const locales: any[] = []; exportLocales.sanitizeAttribs(locales); @@ -320,4 +316,3 @@ describe('ExportLocales', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/marketplace-apps.test.ts b/packages/contentstack-export/test/unit/export/modules/marketplace-apps.test.ts index 6fd9c8b03c..07656a2c9f 100644 --- a/packages/contentstack-export/test/unit/export/modules/marketplace-apps.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/marketplace-apps.test.ts @@ -15,15 +15,13 @@ describe('ExportMarketplaceApps', () => { beforeEach(() => { mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, - apiKey: 'test-api-key', + apiKey: 'test-stack-uid', exportDir: '/test/export', data: '/test/data', branchName: '', - source_stack: 'test-stack-uid', org_uid: 'test-org-uid', context: { command: 'cm:stacks:export', @@ -33,7 +31,7 @@ describe('ExportMarketplaceApps', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -42,7 +40,7 @@ describe('ExportMarketplaceApps', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -54,31 +52,30 @@ describe('ExportMarketplaceApps', () => { writeConcurrency: 5, developerHubBaseUrl: 'https://developer-api.contentstack.io', marketplaceAppEncryptionKey: 'test-encryption-key', - onlyTSModules: [], modules: { types: ['marketplace-apps'], marketplace_apps: { dirName: 'marketplace-apps', - fileName: 'marketplace-apps.json' + fileName: 'marketplace-apps.json', }, 'marketplace-apps': { dirName: 'marketplace-apps', - fileName: 'marketplace-apps.json' + fileName: 'marketplace-apps.json', }, 'composable-studio': { dirName: 'composable-studio', fileName: 'composable-studio.json', apiBaseUrl: 'https://api.contentstack.io', - apiVersion: 'v1' - } + apiVersion: 'v1', + }, }, - query: undefined + query: undefined, } as any; exportMarketplaceApps = new ExportMarketplaceApps({ exportConfig: mockExportConfig, stackAPIClient: {} as any, - moduleName: 'marketplace-apps' as any + moduleName: 'marketplace-apps' as any, }); // Mock app SDK @@ -87,18 +84,18 @@ describe('ExportMarketplaceApps', () => { installation: sinon.stub().returns({ fetchAll: sinon.stub().resolves({ items: [], - count: 0 - }) + count: 0, + }), }), app: sinon.stub().returns({ - fetch: sinon.stub().resolves({}) - }) - }) + fetch: sinon.stub().resolves({}), + }), + }), }; // Mock NodeCrypto mockNodeCrypto = { - encrypt: sinon.stub().returns('encrypted-data') + encrypt: sinon.stub().returns('encrypted-data'), }; // Stub utility functions @@ -169,22 +166,22 @@ describe('ExportMarketplaceApps', () => { { uid: 'installation-1', manifest: { uid: 'app-1', name: 'Test App', visibility: 'public' }, - configuration: {} as any - } + configuration: {} as any, + }, ], - count: 1 - }) + count: 1, + }), }), app: sinon.stub().returns({ - fetch: sinon.stub().resolves({}) - }) + fetch: sinon.stub().resolves({}), + }), }); // marketplaceSDKClient is already stubbed in beforeEach, no need to stub again // getOrgUid and getDeveloperHubUrl are already stubbed in beforeEach, just ensure they resolve correctly (marketplaceAppHelper.getOrgUid as sinon.SinonStub).resolves('test-org-uid'); (marketplaceAppHelper.getDeveloperHubUrl as sinon.SinonStub).resolves('https://developer-api.contentstack.io'); - + // Mock exportApps and getAppManifestAndAppConfig to avoid complex setup const exportAppsStub = sinon.stub(exportMarketplaceApps, 'exportApps').resolves(); const getAppManifestAndAppConfigStub = sinon.stub(exportMarketplaceApps, 'getAppManifestAndAppConfig').resolves(); @@ -216,7 +213,7 @@ describe('ExportMarketplaceApps', () => { await exportMarketplaceApps.start(); expect(exportMarketplaceApps.marketplaceAppPath).to.include('marketplace-apps'); - expect(exportMarketplaceApps.marketplaceAppPath).to.include('/test/data'); + expect(exportMarketplaceApps.marketplaceAppPath).to.include('/test/export'); exportAppsStub.restore(); configHandlerGetStub.restore(); @@ -227,7 +224,7 @@ describe('ExportMarketplaceApps', () => { exportMarketplaceApps = new ExportMarketplaceApps({ exportConfig: mockExportConfig, stackAPIClient: {} as any, - moduleName: 'marketplace-apps' as any + moduleName: 'marketplace-apps' as any, }); const configHandlerGetStub = sinon.stub(utilities.configHandler, 'get'); @@ -247,7 +244,7 @@ describe('ExportMarketplaceApps', () => { exportMarketplaceApps = new ExportMarketplaceApps({ exportConfig: mockExportConfig, stackAPIClient: {} as any, - moduleName: 'marketplace-apps' as any + moduleName: 'marketplace-apps' as any, }); const configHandlerGetStub = sinon.stub(utilities.configHandler, 'get'); @@ -289,9 +286,9 @@ describe('ExportMarketplaceApps', () => { mockExportConfig.query = { modules: { 'marketplace-apps': { - app_uid: { $in: ['app-1', 'app-2'] } - } - } + app_uid: { $in: ['app-1', 'app-2'] }, + }, + }, }; exportMarketplaceApps.exportConfig = mockExportConfig; @@ -305,7 +302,7 @@ describe('ExportMarketplaceApps', () => { // Note: getAppManifestAndAppConfig is called from start(), not exportApps() // So it should not be called when testing exportApps() directly expect(getAppManifestAndAppConfigStub.called).to.be.false; - + getStackSpecificAppsStub.restore(); getAppManifestAndAppConfigStub.restore(); @@ -317,9 +314,9 @@ describe('ExportMarketplaceApps', () => { mockExportConfig.query = { modules: { 'marketplace-apps': { - installation_uid: { $in: ['inst-1', 'inst-2'] } - } - } + installation_uid: { $in: ['inst-1', 'inst-2'] }, + }, + }, }; exportMarketplaceApps.exportConfig = mockExportConfig; @@ -339,8 +336,8 @@ describe('ExportMarketplaceApps', () => { { uid: 'inst-1', manifest: { uid: 'app-1', name: 'Test App' }, - configuration: { key: 'value' } - } + configuration: { key: 'value' }, + }, ]; const getStackSpecificAppsStub = sinon.stub(exportMarketplaceApps, 'getStackSpecificApps').resolves(); @@ -360,9 +357,9 @@ describe('ExportMarketplaceApps', () => { exportMarketplaceApps.installedApps = [ { uid: 'inst-1', - manifest: { uid: 'app-1', name: 'Test App' } + manifest: { uid: 'app-1', name: 'Test App' }, // No configuration property at all - } + }, ]; const getStackSpecificAppsStub = sinon.stub(exportMarketplaceApps, 'getStackSpecificApps').resolves(); @@ -390,22 +387,22 @@ describe('ExportMarketplaceApps', () => { { uid: 'installation-1', manifest: { uid: 'app-1', name: 'Test App 1' }, - someFunction: () => {} + someFunction: () => {}, }, { uid: 'installation-2', manifest: { uid: 'app-2', name: 'Test App 2' }, - someFunction: () => {} - } + someFunction: () => {}, + }, ]; mockAppSdk.marketplace.returns({ installation: sinon.stub().returns({ fetchAll: sinon.stub().resolves({ items: apps, - count: 2 - }) - }) + count: 2, + }), + }), }); await exportMarketplaceApps.getStackSpecificApps(); @@ -424,16 +421,16 @@ describe('ExportMarketplaceApps', () => { if (callCount === 1) { return Promise.resolve({ items: Array(50).fill({ uid: 'app', manifest: {} }), - count: 100 + count: 100, }); } else { return Promise.resolve({ items: Array(50).fill({ uid: 'app2', manifest: {} }), - count: 100 + count: 100, }); } - }) - }) + }), + }), }); await exportMarketplaceApps.getStackSpecificApps(); @@ -450,10 +447,10 @@ describe('ExportMarketplaceApps', () => { callCount++; return Promise.resolve({ items: Array(30).fill({ uid: 'app', manifest: {} }), - count: 30 + count: 30, }); - }) - }) + }), + }), }); await exportMarketplaceApps.getStackSpecificApps(); @@ -465,8 +462,8 @@ describe('ExportMarketplaceApps', () => { it('should handle API errors gracefully', async () => { mockAppSdk.marketplace.returns({ installation: sinon.stub().returns({ - fetchAll: sinon.stub().rejects(new Error('API Error')) - }) + fetchAll: sinon.stub().rejects(new Error('API Error')), + }), }); await exportMarketplaceApps.getStackSpecificApps(); @@ -480,9 +477,9 @@ describe('ExportMarketplaceApps', () => { installation: sinon.stub().returns({ fetchAll: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); const initialLength = exportMarketplaceApps.installedApps.length; @@ -497,16 +494,16 @@ describe('ExportMarketplaceApps', () => { manifest: { uid: 'app-1' }, regularProperty: 'value', functionProperty: () => {}, - anotherFunction: function() {} + anotherFunction: function () {}, }; mockAppSdk.marketplace.returns({ installation: sinon.stub().returns({ fetchAll: sinon.stub().resolves({ items: [appWithFunction], - count: 1 - }) - }) + count: 1, + }), + }), }); await exportMarketplaceApps.getStackSpecificApps(); @@ -540,9 +537,9 @@ describe('ExportMarketplaceApps', () => { manifest: { uid: 'app-1', name: 'Private App', - visibility: 'private' - } - } + visibility: 'private', + }, + }, ]; const getPrivateAppsManifestStub = sinon.stub(exportMarketplaceApps, 'getPrivateAppsManifest').resolves(); @@ -566,9 +563,9 @@ describe('ExportMarketplaceApps', () => { manifest: { uid: 'app-1', name: 'Public App', - visibility: 'public' - } - } + visibility: 'public', + }, + }, ]; const getPrivateAppsManifestStub = sinon.stub(exportMarketplaceApps, 'getPrivateAppsManifest').resolves(); @@ -588,8 +585,8 @@ describe('ExportMarketplaceApps', () => { exportMarketplaceApps.installedApps = [ { uid: 'inst-1', - manifest: { uid: 'app-1', name: 'Test App', visibility: 'public' } - } + manifest: { uid: 'app-1', name: 'Test App', visibility: 'public' }, + }, ]; const getAppConfigurationsStub = sinon.stub(exportMarketplaceApps, 'getAppConfigurations').resolves(); @@ -616,9 +613,9 @@ describe('ExportMarketplaceApps', () => { manifest: { uid: 'app-1', name: 'Private App', - visibility: 'private' - } - } + visibility: 'private', + }, + }, ]; }); @@ -627,13 +624,13 @@ describe('ExportMarketplaceApps', () => { uid: 'app-1', name: 'Private App Updated', visibility: 'private', - oauth: { client_id: 'test-client-id' } + oauth: { client_id: 'test-client-id' }, }; mockAppSdk.marketplace.returns({ app: sinon.stub().returns({ - fetch: sinon.stub().resolves(fetchedManifest) - }) + fetch: sinon.stub().resolves(fetchedManifest), + }), }); await exportMarketplaceApps.getPrivateAppsManifest(0, exportMarketplaceApps.installedApps[0]); @@ -644,8 +641,8 @@ describe('ExportMarketplaceApps', () => { it('should handle API errors gracefully', async () => { mockAppSdk.marketplace.returns({ app: sinon.stub().returns({ - fetch: sinon.stub().rejects(new Error('API Error')) - }) + fetch: sinon.stub().rejects(new Error('API Error')), + }), }); const originalManifest = exportMarketplaceApps.installedApps[0].manifest; @@ -660,8 +657,8 @@ describe('ExportMarketplaceApps', () => { const fetchStub = sinon.stub().resolves({ uid: 'app-1', name: 'Private App' }); mockAppSdk.marketplace.returns({ app: sinon.stub().returns({ - fetch: fetchStub - }) + fetch: fetchStub, + }), }); await exportMarketplaceApps.getPrivateAppsManifest(0, exportMarketplaceApps.installedApps[0]); @@ -681,23 +678,23 @@ describe('ExportMarketplaceApps', () => { uid: 'inst-1', manifest: { uid: 'app-1', - name: 'Test App' - } - } + name: 'Test App', + }, + }, ]; }); it('should fetch and encrypt app configuration', async () => { const installationData = { data: { - configuration: { key: 'value' } - } + configuration: { key: 'value' }, + }, }; mockAppSdk.marketplace.returns({ installation: sinon.stub().returns({ - installationData: sinon.stub().resolves(installationData) - }) + installationData: sinon.stub().resolves(installationData), + }), }); await exportMarketplaceApps.getAppConfigurations(0, exportMarketplaceApps.installedApps[0]); @@ -709,14 +706,14 @@ describe('ExportMarketplaceApps', () => { it('should fetch and encrypt server configuration', async () => { const installationData = { data: { - server_configuration: { secret: 'value' } - } + server_configuration: { secret: 'value' }, + }, }; mockAppSdk.marketplace.returns({ installation: sinon.stub().returns({ - installationData: sinon.stub().resolves(installationData) - }) + installationData: sinon.stub().resolves(installationData), + }), }); await exportMarketplaceApps.getAppConfigurations(0, exportMarketplaceApps.installedApps[0]); @@ -729,14 +726,14 @@ describe('ExportMarketplaceApps', () => { exportMarketplaceApps.nodeCrypto = undefined; const installationData = { data: { - configuration: { key: 'value' } - } + configuration: { key: 'value' }, + }, }; mockAppSdk.marketplace.returns({ installation: sinon.stub().returns({ - installationData: sinon.stub().resolves(installationData) - }) + installationData: sinon.stub().resolves(installationData), + }), }); await exportMarketplaceApps.getAppConfigurations(0, exportMarketplaceApps.installedApps[0]); @@ -748,14 +745,14 @@ describe('ExportMarketplaceApps', () => { it('should handle empty configuration gracefully', async () => { const installationData = { data: { - configuration: null - } as any + configuration: null, + } as any, }; mockAppSdk.marketplace.returns({ installation: sinon.stub().returns({ - installationData: sinon.stub().resolves(installationData) - }) + installationData: sinon.stub().resolves(installationData), + }), }); await exportMarketplaceApps.getAppConfigurations(0, exportMarketplaceApps.installedApps[0]); @@ -766,8 +763,8 @@ describe('ExportMarketplaceApps', () => { it('should handle API errors gracefully', async () => { mockAppSdk.marketplace.returns({ installation: sinon.stub().returns({ - installationData: sinon.stub().rejects(new Error('API Error')) - }) + installationData: sinon.stub().rejects(new Error('API Error')), + }), }); await exportMarketplaceApps.getAppConfigurations(0, exportMarketplaceApps.installedApps[0]); @@ -779,13 +776,13 @@ describe('ExportMarketplaceApps', () => { it('should handle error in installation data response', async () => { const installationData = { data: null, - error: { message: 'Error fetching data' } + error: { message: 'Error fetching data' }, } as any; mockAppSdk.marketplace.returns({ installation: sinon.stub().returns({ - installationData: sinon.stub().resolves(installationData) - }) + installationData: sinon.stub().resolves(installationData), + }), }); await exportMarketplaceApps.getAppConfigurations(0, exportMarketplaceApps.installedApps[0]); @@ -798,14 +795,14 @@ describe('ExportMarketplaceApps', () => { exportMarketplaceApps.installedApps[0].manifest.name = 'Test App Name'; const installationData = { data: { - configuration: { key: 'value' } - } + configuration: { key: 'value' }, + }, }; mockAppSdk.marketplace.returns({ installation: sinon.stub().returns({ - installationData: sinon.stub().resolves(installationData) - }) + installationData: sinon.stub().resolves(installationData), + }), }); await exportMarketplaceApps.getAppConfigurations(0, exportMarketplaceApps.installedApps[0]); @@ -819,14 +816,14 @@ describe('ExportMarketplaceApps', () => { exportMarketplaceApps.installedApps[0].manifest.uid = 'app-uid-123'; const installationData = { data: { - configuration: { key: 'value' } - } + configuration: { key: 'value' }, + }, }; mockAppSdk.marketplace.returns({ installation: sinon.stub().returns({ - installationData: sinon.stub().resolves(installationData) - }) + installationData: sinon.stub().resolves(installationData), + }), }); await exportMarketplaceApps.getAppConfigurations(0, exportMarketplaceApps.installedApps[0]); @@ -836,4 +833,3 @@ describe('ExportMarketplaceApps', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/personalize.test.ts b/packages/contentstack-export/test/unit/export/modules/personalize.test.ts index 93c10c0201..73e27e2f30 100644 --- a/packages/contentstack-export/test/unit/export/modules/personalize.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/personalize.test.ts @@ -17,7 +17,6 @@ describe('ExportPersonalize', () => { beforeEach(() => { mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -33,7 +32,7 @@ describe('ExportPersonalize', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -42,7 +41,7 @@ describe('ExportPersonalize', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -54,7 +53,6 @@ describe('ExportPersonalize', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['personalize'], personalize: { @@ -67,34 +65,34 @@ describe('ExportPersonalize', () => { 'AZURE-EU': 'https://azure-eu-personalize-api.contentstack.com', 'GCP-NA': 'https://gcp-na-personalize-api.contentstack.com', 'GCP-EU': 'https://gcp-eu-personalize-api.contentstack.com', - 'us': 'https://personalize-api.contentstack.com' + us: 'https://personalize-api.contentstack.com', }, exportOrder: ['events', 'attributes', 'audiences', 'experiences'], projects: { dirName: 'projects', - fileName: 'projects.json' + fileName: 'projects.json', }, attributes: { dirName: 'attributes', - fileName: 'attributes.json' + fileName: 'attributes.json', }, audiences: { dirName: 'audiences', - fileName: 'audiences.json' + fileName: 'audiences.json', }, events: { dirName: 'events', - fileName: 'events.json' + fileName: 'events.json', }, experiences: { dirName: 'experiences', fileName: 'experiences.json', thresholdTimer: 60000, - checkIntervalDuration: 10000 - } - } + checkIntervalDuration: 10000, + }, + }, }, - management_token: undefined + management_token: undefined, } as any; // Mock ExportProjects - this can modify personalizationEnabled @@ -106,36 +104,46 @@ describe('ExportPersonalize', () => { }), init: sinon.stub().resolves(), projects: sinon.stub().resolves([{ uid: 'project-1' }]), // Return array with at least one project - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }; // Mock ExportEvents mockExportEvents = { - start: sinon.stub().resolves() + start: sinon.stub().resolves(), }; // Mock ExportAttributes mockExportAttributes = { - start: sinon.stub().resolves() + start: sinon.stub().resolves(), }; // Mock ExportAudiences mockExportAudiences = { - start: sinon.stub().resolves() + start: sinon.stub().resolves(), }; // Mock ExportExperiences mockExportExperiences = { - start: sinon.stub().resolves() + start: sinon.stub().resolves(), }; // Stub the variant class constructors - these need to return the mock instances - sinon.stub(variants, 'ExportProjects').value(function() { return mockExportProjects; } as any); - sinon.stub(variants, 'ExportEvents').value(function() { return mockExportEvents; } as any); - sinon.stub(variants, 'ExportAttributes').value(function() { return mockExportAttributes; } as any); - sinon.stub(variants, 'ExportAudiences').value(function() { return mockExportAudiences; } as any); - sinon.stub(variants, 'ExportExperiences').value(function() { return mockExportExperiences; } as any); - + sinon.stub(variants, 'ExportProjects').value(function () { + return mockExportProjects; + } as any); + sinon.stub(variants, 'ExportEvents').value(function () { + return mockExportEvents; + } as any); + sinon.stub(variants, 'ExportAttributes').value(function () { + return mockExportAttributes; + } as any); + sinon.stub(variants, 'ExportAudiences').value(function () { + return mockExportAudiences; + } as any); + sinon.stub(variants, 'ExportExperiences').value(function () { + return mockExportExperiences; + } as any); + // Ensure all mock modules have setParentProgressManager mockExportEvents.setParentProgressManager = sinon.stub(); mockExportAttributes.setParentProgressManager = sinon.stub(); @@ -145,7 +153,7 @@ describe('ExportPersonalize', () => { exportPersonalize = new ExportPersonalize({ exportConfig: mockExportConfig, stackAPIClient: {} as any, - moduleName: 'personalize' + moduleName: 'personalize', }); }); @@ -164,7 +172,12 @@ describe('ExportPersonalize', () => { expect(exportPersonalize.personalizeConfig).to.exist; expect(exportPersonalize.personalizeConfig.dirName).to.equal('personalize'); expect(exportPersonalize.personalizeConfig.baseURL).to.deep.equal(mockExportConfig.modules.personalize.baseURL); - expect(exportPersonalize.personalizeConfig.exportOrder).to.deep.equal(['events', 'attributes', 'audiences', 'experiences']); + expect(exportPersonalize.personalizeConfig.exportOrder).to.deep.equal([ + 'events', + 'attributes', + 'audiences', + 'experiences', + ]); }); }); @@ -175,7 +188,7 @@ describe('ExportPersonalize', () => { exportPersonalize = new ExportPersonalize({ exportConfig: mockExportConfig, stackAPIClient: {} as any, - moduleName: 'personalize' + moduleName: 'personalize', }); await exportPersonalize.start(); @@ -207,7 +220,7 @@ describe('ExportPersonalize', () => { exportPersonalize = new ExportPersonalize({ exportConfig: mockExportConfig, stackAPIClient: {} as any, - moduleName: 'personalize' + moduleName: 'personalize', }); await exportPersonalize.start(); @@ -283,7 +296,10 @@ describe('ExportPersonalize', () => { mockExportProjects.init.resolves(); mockExportProjects.projects.resolves([{ uid: 'project-1' }]); // Ensure exportOrder is set - if (!mockExportConfig.modules.personalize.exportOrder || mockExportConfig.modules.personalize.exportOrder.length === 0) { + if ( + !mockExportConfig.modules.personalize.exportOrder || + mockExportConfig.modules.personalize.exportOrder.length === 0 + ) { mockExportConfig.modules.personalize.exportOrder = ['events', 'attributes', 'audiences', 'experiences']; } }); @@ -318,28 +334,28 @@ describe('ExportPersonalize', () => { expect(currentModule).to.be.null; currentModule = 'events'; moduleStartTimes.events = Date.now(); - await new Promise(resolve => setTimeout(resolve, 10)); + await new Promise((resolve) => setTimeout(resolve, 10)); currentModule = null; }); mockExportAttributes.start.callsFake(async () => { expect(currentModule).to.be.null; currentModule = 'attributes'; moduleStartTimes.attributes = Date.now(); - await new Promise(resolve => setTimeout(resolve, 10)); + await new Promise((resolve) => setTimeout(resolve, 10)); currentModule = null; }); mockExportAudiences.start.callsFake(async () => { expect(currentModule).to.be.null; currentModule = 'audiences'; moduleStartTimes.audiences = Date.now(); - await new Promise(resolve => setTimeout(resolve, 10)); + await new Promise((resolve) => setTimeout(resolve, 10)); currentModule = null; }); mockExportExperiences.start.callsFake(async () => { expect(currentModule).to.be.null; currentModule = 'experiences'; moduleStartTimes.experiences = Date.now(); - await new Promise(resolve => setTimeout(resolve, 10)); + await new Promise((resolve) => setTimeout(resolve, 10)); currentModule = null; }); @@ -389,7 +405,7 @@ describe('ExportPersonalize', () => { describe('start() method - Unknown Module Handling', () => { let validateProjectConnectivityStub: sinon.SinonStub; let validatePersonalizeSetupStub: sinon.SinonStub; - + beforeEach(() => { // Ensure projects are found so personalizationEnabled is set to true mockExportProjects.init.resolves(); @@ -399,7 +415,7 @@ describe('ExportPersonalize', () => { // Stub validatePersonalizeSetup to return true validatePersonalizeSetupStub = sinon.stub(exportPersonalize, 'validatePersonalizeSetup' as any).returns(true); }); - + afterEach(() => { if (validateProjectConnectivityStub) { validateProjectConnectivityStub.restore(); @@ -418,18 +434,20 @@ describe('ExportPersonalize', () => { validateProjectConnectivityStub.resolves(1); validatePersonalizeSetupStub.returns(true); // Stub withLoadingSpinner to execute the function immediately - sinon.stub(exportPersonalize, 'withLoadingSpinner' as any).callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(exportPersonalize, 'withLoadingSpinner' as any) + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); // Stub createNestedProgress to return a mock progress manager const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ - updateStatus: sinon.stub() + updateStatus: sinon.stub(), }), updateStatus: sinon.stub(), completeProcess: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(exportPersonalize, 'createNestedProgress' as any).returns(mockProgress); sinon.stub(exportPersonalize, 'completeProgress' as any); @@ -465,18 +483,20 @@ describe('ExportPersonalize', () => { validateProjectConnectivityStub.resolves(1); validatePersonalizeSetupStub.returns(true); // Stub withLoadingSpinner to execute the function immediately - sinon.stub(exportPersonalize, 'withLoadingSpinner' as any).callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(exportPersonalize, 'withLoadingSpinner' as any) + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); // Stub createNestedProgress to return a mock progress manager const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ - updateStatus: sinon.stub() + updateStatus: sinon.stub(), }), updateStatus: sinon.stub(), completeProcess: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(exportPersonalize, 'createNestedProgress' as any).returns(mockProgress); sinon.stub(exportPersonalize, 'completeProgress' as any); @@ -569,13 +589,13 @@ describe('ExportPersonalize', () => { describe('start() method - Region Configuration', () => { it('should work with all supported region names', async () => { const supportedRegions = ['AWS-NA', 'AWS-EU', 'AWS-AU', 'AZURE-NA', 'AZURE-EU', 'GCP-NA', 'GCP-EU', 'us']; - + for (const regionName of supportedRegions) { mockExportConfig.region.name = regionName; exportPersonalize = new ExportPersonalize({ exportConfig: mockExportConfig, stackAPIClient: {} as any, - moduleName: 'personalize' + moduleName: 'personalize', }); mockExportProjects.init.resolves(); @@ -595,7 +615,7 @@ describe('ExportPersonalize', () => { // Ensure projects are found so personalizationEnabled is set to true mockExportProjects.init.resolves(); mockExportProjects.projects.resolves([{ uid: 'project-1' }]); - + // Track execution order to verify sequential processing const executionOrder: string[] = []; mockExportEvents.start.callsFake(async () => { @@ -632,11 +652,11 @@ describe('ExportPersonalize', () => { // Setup: ExportProjects enables personalization, first module succeeds, second fails mockExportProjects.init.resolves(); mockExportProjects.projects.resolves([{ uid: 'project-1' }]); - + const attributesError = new Error('Attributes export failed'); mockExportEvents.start.resolves(); mockExportAttributes.start.rejects(attributesError); - + const handleAndLogErrorSpy = sinon.spy(); sinon.replaceGetter(utilities, 'handleAndLogError', () => handleAndLogErrorSpy); diff --git a/packages/contentstack-export/test/unit/export/modules/stack.test.ts b/packages/contentstack-export/test/unit/export/modules/stack.test.ts index 8fa749c724..52645c0281 100644 --- a/packages/contentstack-export/test/unit/export/modules/stack.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/stack.test.ts @@ -13,25 +13,22 @@ describe('ExportStack', () => { beforeEach(() => { mockStackClient = { fetch: sinon.stub().resolves({ name: 'Test Stack', uid: 'stack-uid', org_uid: 'org-uid' }), - settings: sinon.stub().resolves({ - name: 'Stack Settings', + settings: sinon.stub().resolves({ + name: 'Stack Settings', description: 'Stack settings description', - settings: { global: { example: 'value' } } + settings: { global: { example: 'value' } }, }), locale: sinon.stub().returns({ query: sinon.stub().returns({ - find: sinon.stub().resolves({ - items: [ - { uid: 'locale-1', name: 'English (United States)', code: 'en-us', fallback_locale: null } - ], - count: 1 - }) - }) - }) + find: sinon.stub().resolves({ + items: [{ uid: 'locale-1', name: 'English (United States)', code: 'en-us', fallback_locale: null }], + count: 1, + }), + }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -52,7 +49,7 @@ describe('ExportStack', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -62,7 +59,7 @@ describe('ExportStack', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -79,64 +76,63 @@ describe('ExportStack', () => { users: '', extension: '', webhooks: '', - stacks: '' + stacks: '', }, personalizationEnabled: false, fetchConcurrency: 5, writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['stack'], locales: { dirName: 'locales', fileName: 'locales.json', - requiredKeys: ['code'] + requiredKeys: ['code'], }, customRoles: { dirName: 'custom_roles', fileName: 'custom_roles.json', - customRolesLocalesFileName: '' + customRolesLocalesFileName: '', }, 'custom-roles': { dirName: 'custom_roles', fileName: 'custom_roles.json', - customRolesLocalesFileName: '' + customRolesLocalesFileName: '', }, environments: { dirName: 'environments', - fileName: 'environments.json' + fileName: 'environments.json', }, labels: { dirName: 'labels', fileName: 'labels.json', - invalidKeys: [] + invalidKeys: [], }, webhooks: { dirName: 'webhooks', - fileName: 'webhooks.json' + fileName: 'webhooks.json', }, releases: { dirName: 'releases', fileName: 'releases.json', releasesList: 'releases_list.json', - invalidKeys: [] + invalidKeys: [], }, workflows: { dirName: 'workflows', fileName: 'workflows.json', - invalidKeys: [] + invalidKeys: [], }, globalfields: { dirName: 'global_fields', fileName: 'globalfields.json', - validKeys: ['title', 'uid'] + validKeys: ['title', 'uid'], }, 'global-fields': { dirName: 'global_fields', fileName: 'globalfields.json', - validKeys: ['title', 'uid'] + validKeys: ['title', 'uid'], }, assets: { dirName: 'assets', @@ -151,19 +147,19 @@ describe('ExportStack', () => { securedAssets: false, displayExecutionTime: false, enableDownloadStatus: false, - includeVersionedAssets: false + includeVersionedAssets: false, }, content_types: { dirName: 'content_types', fileName: 'content_types.json', validKeys: ['title', 'uid'], - limit: 100 + limit: 100, }, 'content-types': { dirName: 'content_types', fileName: 'content_types.json', validKeys: ['title', 'uid'], - limit: 100 + limit: 100, }, entries: { dirName: 'entries', @@ -172,71 +168,71 @@ describe('ExportStack', () => { batchLimit: 100, downloadLimit: 5, limit: 100, - exportVersions: false + exportVersions: false, }, personalize: { dirName: 'personalize', - baseURL: {} + baseURL: {}, }, variantEntry: { dirName: 'variant_entries', fileName: 'variant_entries.json', chunkFileSize: 5, - query: { skip: 0, limit: 100, include_variant: true, include_count: false, include_publish_details: true } + query: { skip: 0, limit: 100, include_variant: true, include_count: false, include_publish_details: true }, }, extensions: { dirName: 'extensions', - fileName: 'extensions.json' + fileName: 'extensions.json', }, stack: { dirName: 'stack', fileName: 'stack.json', - limit: 100 + limit: 100, }, dependency: { - entries: [] + entries: [], }, marketplace_apps: { dirName: 'marketplace_apps', - fileName: 'marketplace_apps.json' + fileName: 'marketplace_apps.json', }, 'marketplace-apps': { dirName: 'marketplace_apps', - fileName: 'marketplace_apps.json' + fileName: 'marketplace_apps.json', }, masterLocale: { dirName: 'master_locale', fileName: 'master_locale.json', - requiredKeys: ['code'] + requiredKeys: ['code'], }, taxonomies: { dirName: 'taxonomies', fileName: 'taxonomies.json', invalidKeys: [], - limit: 100 + limit: 100, }, events: { dirName: 'events', fileName: 'events.json', - invalidKeys: [] + invalidKeys: [], }, audiences: { dirName: 'audiences', fileName: 'audiences.json', - invalidKeys: [] + invalidKeys: [], }, attributes: { dirName: 'attributes', fileName: 'attributes.json', - invalidKeys: [] - } - } + invalidKeys: [], + }, + }, } as any; exportStack = new ExportStack({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'stack' + moduleName: 'stack', }); // Stub FsUtility methods @@ -269,7 +265,7 @@ describe('ExportStack', () => { describe('getLocales() method', () => { it('should fetch and return master locale', async () => { const locale = await exportStack.getLocales(); - + expect(locale).to.exist; expect(locale.code).to.equal('en-us'); expect(locale.name).to.equal('English (United States)'); @@ -285,22 +281,22 @@ describe('ExportStack', () => { // First batch without master locale return Promise.resolve({ items: new Array(100).fill({ uid: 'locale-test', code: 'en', fallback_locale: 'en-us' }), - count: 150 + count: 150, }); } else { // Second batch with master locale return Promise.resolve({ items: [{ uid: 'locale-master', code: 'en-us', fallback_locale: null, name: 'English' }], - count: 150 + count: 150, }); } - }) - }) + }), + }), }; - + mockStackClient.locale.returns(localeStub); const locale = await exportStack.getLocales(); - + expect(callCount).to.be.greaterThan(1); expect(locale.code).to.equal('en-us'); }); @@ -308,12 +304,12 @@ describe('ExportStack', () => { it('should handle error when fetching locales', async () => { const localeStub = { query: sinon.stub().returns({ - find: sinon.stub().rejects(new Error('API Error')) - }) + find: sinon.stub().rejects(new Error('API Error')), + }), }; - + mockStackClient.locale.returns(localeStub); - + try { await exportStack.getLocales(); expect.fail('Should have thrown an error'); @@ -327,14 +323,14 @@ describe('ExportStack', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }; - + mockStackClient.locale.returns(localeStub); const locale = await exportStack.getLocales(); - + expect(locale).to.be.undefined; }); @@ -349,15 +345,15 @@ describe('ExportStack', () => { // First call: 100 items, count 100, skip will be 100, which equals count, so it stops return Promise.resolve({ items: Array(limit).fill({ uid: `locale-${callCount}`, code: 'en', fallback_locale: 'en-us' }), - count: limit // Only limit items, so skip will equal count and stop + count: limit, // Only limit items, so skip will equal count and stop }); - }) - }) + }), + }), }; - + mockStackClient.locale.returns(localeStub); const locale = await exportStack.getLocales(); - + // Should return undefined when master locale not found after all pages expect(locale).to.be.undefined; // Should have searched through available pages @@ -369,14 +365,14 @@ describe('ExportStack', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [{ uid: 'locale-master', code: 'en-us', fallback_locale: null, name: 'English' }], - count: 1 - }) - }) + count: 1, + }), + }), }; - + mockStackClient.locale.returns(localeStub); const locale = await exportStack.getLocales(100); - + // Should find master locale even when starting with skip expect(locale).to.exist; expect(locale.code).to.equal('en-us'); @@ -388,14 +384,14 @@ describe('ExportStack', () => { const localeError = new Error('Locale fetch failed'); const localeStub = { query: sinon.stub().returns({ - find: sinon.stub().rejects(localeError) - }) + find: sinon.stub().rejects(localeError), + }), }; - + mockStackClient.locale.returns(localeStub); const handleAndLogErrorSpy = sinon.spy(); sinon.replaceGetter(utilities, 'handleAndLogError', () => handleAndLogErrorSpy); - + try { await exportStack.getLocales(); expect.fail('Should have thrown error'); @@ -403,10 +399,7 @@ describe('ExportStack', () => { expect(error).to.equal(localeError); // Should handle and log error expect(handleAndLogErrorSpy.called).to.be.true; - expect(handleAndLogErrorSpy.calledWith( - localeError, - sinon.match.has('module', 'stack') - )).to.be.true; + expect(handleAndLogErrorSpy.calledWith(localeError, sinon.match.has('module', 'stack'))).to.be.true; } }); @@ -416,16 +409,16 @@ describe('ExportStack', () => { find: sinon.stub().resolves({ items: [ { uid: 'locale-1', code: 'es-es', fallback_locale: 'en-us' }, - { uid: 'locale-master', code: 'en-us', fallback_locale: null, name: 'English' } + { uid: 'locale-master', code: 'en-us', fallback_locale: null, name: 'English' }, ], - count: 2 - }) - }) + count: 2, + }), + }), }; - + mockStackClient.locale.returns(localeStub); const locale = await exportStack.getLocales(); - + expect(locale.code).to.equal('en-us'); }); }); @@ -436,9 +429,9 @@ describe('ExportStack', () => { const makeDirectoryStub = FsUtility.prototype.makeDirectory as sinon.SinonStub; const stackData = { name: 'Test Stack', uid: 'stack-uid', org_uid: 'org-123' }; mockStackClient.fetch = sinon.stub().resolves(stackData); - + const result = await exportStack.exportStack(); - + expect(writeFileStub.called).to.be.true; expect(makeDirectoryStub.called).to.be.true; // Should return the stack data @@ -454,27 +447,24 @@ describe('ExportStack', () => { mockStackClient.fetch = sinon.stub().rejects(stackError); const handleAndLogErrorSpy = sinon.spy(); sinon.replaceGetter(utilities, 'handleAndLogError', () => handleAndLogErrorSpy); - + // Should complete without throwing despite error const result = await exportStack.exportStack(); - + // Should return undefined on error expect(result).to.be.undefined; // Should handle and log error expect(handleAndLogErrorSpy.called).to.be.true; - expect(handleAndLogErrorSpy.calledWith( - stackError, - sinon.match.has('module', 'stack') - )).to.be.true; + expect(handleAndLogErrorSpy.calledWith(stackError, sinon.match.has('module', 'stack'))).to.be.true; }); it('should create directory before writing stack file', async () => { const makeDirectoryStub = FsUtility.prototype.makeDirectory as sinon.SinonStub; const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; mockStackClient.fetch = sinon.stub().resolves({ name: 'Test Stack' }); - + await exportStack.exportStack(); - + // Directory should be created before file write expect(makeDirectoryStub.called).to.be.true; expect(writeFileStub.called).to.be.true; @@ -487,15 +477,15 @@ describe('ExportStack', () => { it('should export stack settings successfully and write to file', async () => { const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; const makeDirectoryStub = FsUtility.prototype.makeDirectory as sinon.SinonStub; - const settingsData = { - name: 'Stack Settings', + const settingsData = { + name: 'Stack Settings', description: 'Settings description', - settings: { global: { example: 'value' } } + settings: { global: { example: 'value' } }, }; mockStackClient.settings = sinon.stub().resolves(settingsData); - + const result = await exportStack.exportStackSettings(); - + expect(writeFileStub.called).to.be.true; expect(makeDirectoryStub.called).to.be.true; // Should return the settings data @@ -514,24 +504,21 @@ describe('ExportStack', () => { // Should complete without throwing despite error const result = await exportStack.exportStackSettings(); - + // Should return undefined on error expect(result).to.be.undefined; // Should handle and log error expect(handleAndLogErrorSpy.called).to.be.true; - expect(handleAndLogErrorSpy.calledWith( - settingsError, - sinon.match.has('module', 'stack') - )).to.be.true; + expect(handleAndLogErrorSpy.calledWith(settingsError, sinon.match.has('module', 'stack'))).to.be.true; }); it('should create directory before writing settings file', async () => { const makeDirectoryStub = FsUtility.prototype.makeDirectory as sinon.SinonStub; const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; mockStackClient.settings = sinon.stub().resolves({ name: 'Settings' }); - + await exportStack.exportStackSettings(); - + // Directory should be created before file write expect(makeDirectoryStub.called).to.be.true; expect(writeFileStub.called).to.be.true; @@ -545,13 +532,13 @@ describe('ExportStack', () => { const exportStackStub = sinon.stub(exportStack, 'exportStack').resolves({ name: 'test-stack' }); const exportStackSettingsStub = sinon.stub(exportStack, 'exportStackSettings').resolves(); const getStackStub = sinon.stub(exportStack, 'getStack').resolves({}); - + exportStack.exportConfig.preserveStackVersion = true; - + await exportStack.start(); - + expect(exportStackStub.called).to.be.true; - + exportStackStub.restore(); exportStackSettingsStub.restore(); getStackStub.restore(); @@ -560,20 +547,19 @@ describe('ExportStack', () => { it('should skip exportStackSettings when management_token is present', async () => { const getStackStub = sinon.stub(exportStack, 'getStack').resolves({}); const exportStackSettingsSpy = sinon.spy(exportStack, 'exportStackSettings'); - + exportStack.exportConfig.management_token = 'some-token'; exportStack.exportConfig.preserveStackVersion = false; exportStack.exportConfig.master_locale = { code: 'en-us' }; exportStack.exportConfig.hasOwnProperty = sinon.stub().returns(true); - + await exportStack.start(); - + // Verify exportStackSettings was NOT called expect(exportStackSettingsSpy.called).to.be.false; - + getStackStub.restore(); exportStackSettingsSpy.restore(); }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts b/packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts index 06b86229ad..a9d2764b92 100644 --- a/packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/taxonomies.test.ts @@ -16,16 +16,15 @@ describe('ExportTaxonomies', () => { find: sinon.stub().resolves({ items: [ { uid: 'taxonomy-1', name: 'Category' }, - { uid: 'taxonomy-2', name: 'Tag' } + { uid: 'taxonomy-2', name: 'Tag' }, ], - count: 2 - }) - }) - }) + count: 2, + }), + }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -41,7 +40,7 @@ describe('ExportTaxonomies', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -50,7 +49,7 @@ describe('ExportTaxonomies', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -62,27 +61,26 @@ describe('ExportTaxonomies', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['taxonomies'], taxonomies: { dirName: 'taxonomies', fileName: 'taxonomies.json', invalidKeys: [], - limit: 100 + limit: 100, }, locales: { dirName: 'locales', fileName: 'locales.json', - requiredKeys: ['code', 'uid', 'name', 'fallback_locale'] - } - } + requiredKeys: ['code', 'uid', 'name', 'fallback_locale'], + }, + }, } as any; exportTaxonomies = new ExportTaxonomies({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'taxonomies' + moduleName: 'taxonomies', }); sinon.stub(FsUtility.prototype, 'writeFile').resolves(); @@ -112,20 +110,20 @@ describe('ExportTaxonomies', () => { it('should fetch and process taxonomies correctly', async () => { const taxonomies = [ { uid: 'taxonomy-1', name: 'Category', invalidField: 'remove' }, - { uid: 'taxonomy-2', name: 'Tag', invalidField: 'remove' } + { uid: 'taxonomy-2', name: 'Tag', invalidField: 'remove' }, ]; mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: taxonomies, - count: 2 - }) - }) + count: 2, + }), + }), }); await exportTaxonomies.fetchTaxonomies(); - + // Verify taxonomies were processed expect(Object.keys(exportTaxonomies.taxonomies).length).to.equal(2); expect(exportTaxonomies.taxonomies['taxonomy-1']).to.exist; @@ -141,20 +139,20 @@ describe('ExportTaxonomies', () => { if (callCount === 1) { return Promise.resolve({ items: Array(100).fill({ uid: `taxonomy-${callCount}`, name: 'Test' }), - count: 150 + count: 150, }); } else { return Promise.resolve({ items: Array(50).fill({ uid: `taxonomy-${callCount}`, name: 'Test' }), - count: 150 + count: 150, }); } - }) - }) + }), + }), }); await exportTaxonomies.fetchTaxonomies(); - + // Verify multiple calls were made expect(callCount).to.be.greaterThan(1); }); @@ -164,52 +162,52 @@ describe('ExportTaxonomies', () => { it('should complete full export flow and call makeAPICall for each taxonomy', async () => { const mockMakeAPICall = sinon.stub(exportTaxonomies, 'makeAPICall').resolves(); const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; - + // Mock fetchTaxonomies to return one taxonomy const mockTaxonomy = { uid: 'taxonomy-1', - name: 'Category' + name: 'Category', }; - + // Mock the API call to return taxonomies mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [mockTaxonomy], - count: 1 - }) - }) + count: 1, + }), + }), }); await exportTaxonomies.start(); - + // Verify makeAPICall was called for the taxonomy expect(mockMakeAPICall.called).to.be.true; expect(mockMakeAPICall.callCount).to.equal(1); // Verify writeFile was called for taxonomies.json expect(writeFileStub.called).to.be.true; - + mockMakeAPICall.restore(); }); it('should handle empty taxonomies and not call makeAPICall', async () => { const mockMakeAPICall = sinon.stub(exportTaxonomies, 'makeAPICall').resolves(); - + mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); exportTaxonomies.taxonomies = {}; await exportTaxonomies.start(); - + // Verify makeAPICall was NOT called when taxonomies are empty expect(mockMakeAPICall.called).to.be.false; - + mockMakeAPICall.restore(); }); }); @@ -220,14 +218,14 @@ describe('ExportTaxonomies', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: [], - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = Object.keys(exportTaxonomies.taxonomies).length; await exportTaxonomies.fetchTaxonomies(); - + // Verify no new taxonomies were added expect(Object.keys(exportTaxonomies.taxonomies).length).to.equal(initialCount); }); @@ -237,14 +235,14 @@ describe('ExportTaxonomies', () => { query: sinon.stub().returns({ find: sinon.stub().resolves({ items: null, - count: 0 - }) - }) + count: 0, + }), + }), }); const initialCount = Object.keys(exportTaxonomies.taxonomies).length; await exportTaxonomies.fetchTaxonomies(); - + // Verify no processing occurred with null items expect(Object.keys(exportTaxonomies.taxonomies).length).to.equal(initialCount); }); @@ -252,30 +250,30 @@ describe('ExportTaxonomies', () => { it('should handle API errors gracefully without crashing', async () => { mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(new Error('API Error')) - }) + find: sinon.stub().rejects(new Error('API Error')), + }), }); await exportTaxonomies.fetchTaxonomies(); - + // Verify method completes without throwing expect(exportTaxonomies.taxonomies).to.exist; }); it('should handle count undefined scenario and use items length', async () => { const taxonomies = [{ uid: 'taxonomy-1', name: 'Category' }]; - + mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: taxonomies, - count: undefined - }) - }) + count: undefined, + }), + }), }); await exportTaxonomies.fetchTaxonomies(); - + // Verify taxonomies were still processed despite undefined count expect(exportTaxonomies.taxonomies['taxonomy-1']).to.exist; }); @@ -285,7 +283,7 @@ describe('ExportTaxonomies', () => { it('should sanitize taxonomy attributes', () => { const taxonomies = [ { uid: 'taxonomy-1', name: 'Category', invalidField: 'remove' }, - { uid: 'taxonomy-2', name: 'Tag', invalidField: 'remove' } + { uid: 'taxonomy-2', name: 'Tag', invalidField: 'remove' }, ]; exportTaxonomies.sanitizeTaxonomiesAttribs(taxonomies); @@ -295,9 +293,7 @@ describe('ExportTaxonomies', () => { }); it('should handle taxonomies without name field', () => { - const taxonomies = [ - { uid: 'taxonomy-1', invalidField: 'remove' } - ]; + const taxonomies = [{ uid: 'taxonomy-1', invalidField: 'remove' }]; exportTaxonomies.sanitizeTaxonomiesAttribs(taxonomies); @@ -373,7 +369,7 @@ describe('ExportTaxonomies', () => { it('should handle locales file with missing code field', () => { const localesData = { 'locale-1': { name: 'English' }, // missing code - 'locale-2': { code: 'es-es', name: 'Spanish' } + 'locale-2': { code: 'es-es', name: 'Spanish' }, }; const readFileStub = FsUtility.prototype.readFile as sinon.SinonStub; readFileStub.returns(localesData); @@ -390,7 +386,7 @@ describe('ExportTaxonomies', () => { const localesData = { 'locale-1': { code: 'en-us', name: 'English US' }, 'locale-2': { code: 'en-us', name: 'English UK' }, // duplicate code - 'locale-3': { code: 'es-es', name: 'Spanish' } + 'locale-3': { code: 'es-es', name: 'Spanish' }, }; const readFileStub = FsUtility.prototype.readFile as sinon.SinonStub; readFileStub.returns(localesData); @@ -451,7 +447,6 @@ describe('ExportTaxonomies', () => { }); describe('writeTaxonomiesMetadata() method', () => { - it('should skip writing when taxonomies object is empty', () => { const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; exportTaxonomies.taxonomies = {}; @@ -475,16 +470,16 @@ describe('ExportTaxonomies', () => { it('should fetch taxonomies with locale code', async () => { const taxonomies = [ { uid: 'taxonomy-1', name: 'Category', locale: 'en-us' }, - { uid: 'taxonomy-2', name: 'Tag', locale: 'en-us' } + { uid: 'taxonomy-2', name: 'Tag', locale: 'en-us' }, ]; mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: taxonomies, - count: 2 - }) - }) + count: 2, + }), + }), }); await exportTaxonomies.fetchTaxonomies('en-us'); @@ -495,17 +490,15 @@ describe('ExportTaxonomies', () => { }); it('should detect locale-based export support when items have locale field', async () => { - const taxonomies = [ - { uid: 'taxonomy-1', name: 'Category', locale: 'en-us' } - ]; + const taxonomies = [{ uid: 'taxonomy-1', name: 'Category', locale: 'en-us' }]; mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: taxonomies, - count: 1 - }) - }) + count: 1, + }), + }), }); await exportTaxonomies.fetchTaxonomies('en-us', true); @@ -516,16 +509,16 @@ describe('ExportTaxonomies', () => { it('should disable locale-based export when items lack locale field', async () => { const taxonomies = [ - { uid: 'taxonomy-1', name: 'Category' } // no locale field + { uid: 'taxonomy-1', name: 'Category' }, // no locale field ]; mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ find: sinon.stub().resolves({ items: taxonomies, - count: 1 - }) - }) + count: 1, + }), + }), }); await exportTaxonomies.fetchTaxonomies('en-us', true); @@ -539,11 +532,11 @@ describe('ExportTaxonomies', () => { const apiError: any = new Error('API Error'); apiError.status = 500; apiError.errors = { general: ['Internal server error'] }; - + mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(apiError) - }) + find: sinon.stub().rejects(apiError), + }), }); await exportTaxonomies.fetchTaxonomies('en-us', true); @@ -558,13 +551,15 @@ describe('ExportTaxonomies', () => { planLimitationError.status = 403; planLimitationError.statusText = 'Forbidden'; planLimitationError.errors = { - taxonomies: ['Taxonomy localization is not included in your plan. Please contact the support@contentstack.com team for assistance.'] + taxonomies: [ + 'Taxonomy localization is not included in your plan. Please contact the support@contentstack.com team for assistance.', + ], }; - + mockStackClient.taxonomy.returns({ query: sinon.stub().returns({ - find: sinon.stub().rejects(planLimitationError) - }) + find: sinon.stub().rejects(planLimitationError), + }), }); await exportTaxonomies.fetchTaxonomies('en-us', true); @@ -575,7 +570,6 @@ describe('ExportTaxonomies', () => { }); describe('exportTaxonomies() method - locale-based export', () => { - it('should skip export when no taxonomies for locale', async () => { const mockMakeAPICall = sinon.stub(exportTaxonomies, 'makeAPICall').resolves(); exportTaxonomies.taxonomiesByLocale['en-us'] = new Set(); @@ -590,11 +584,13 @@ describe('ExportTaxonomies', () => { describe('start() method - locale-based export scenarios', () => { it('should use legacy export when locale-based export is not supported', async () => { - const mockFetchTaxonomies = sinon.stub(exportTaxonomies, 'fetchTaxonomies').callsFake(async (locale, checkSupport) => { - if (checkSupport) { - exportTaxonomies.isLocaleBasedExportSupported = false; - } - }); + const mockFetchTaxonomies = sinon + .stub(exportTaxonomies, 'fetchTaxonomies') + .callsFake(async (locale, checkSupport) => { + if (checkSupport) { + exportTaxonomies.isLocaleBasedExportSupported = false; + } + }); const mockExportTaxonomies = sinon.stub(exportTaxonomies, 'exportTaxonomies').resolves(); const mockWriteMetadata = sinon.stub(exportTaxonomies, 'writeTaxonomiesMetadata').resolves(); const mockGetLocales = sinon.stub(exportTaxonomies, 'getLocalesToExport').returns(['en-us']); @@ -614,17 +610,19 @@ describe('ExportTaxonomies', () => { it('should clear taxonomies and re-fetch when falling back to legacy export', async () => { let fetchCallCount = 0; - const mockFetchTaxonomies = sinon.stub(exportTaxonomies, 'fetchTaxonomies').callsFake(async (locale, checkSupport) => { - fetchCallCount++; - if (checkSupport) { - // First call fails locale check - exportTaxonomies.isLocaleBasedExportSupported = false; - exportTaxonomies.taxonomies = { 'partial-data': { uid: 'partial-data' } }; // Simulate partial data - } else { - // Second call should have cleared data - expect(exportTaxonomies.taxonomies).to.deep.equal({}); - } - }); + const mockFetchTaxonomies = sinon + .stub(exportTaxonomies, 'fetchTaxonomies') + .callsFake(async (locale, checkSupport) => { + fetchCallCount++; + if (checkSupport) { + // First call fails locale check + exportTaxonomies.isLocaleBasedExportSupported = false; + exportTaxonomies.taxonomies = { 'partial-data': { uid: 'partial-data' } }; // Simulate partial data + } else { + // Second call should have cleared data + expect(exportTaxonomies.taxonomies).to.deep.equal({}); + } + }); const mockExportTaxonomies = sinon.stub(exportTaxonomies, 'exportTaxonomies').resolves(); const mockWriteMetadata = sinon.stub(exportTaxonomies, 'writeTaxonomiesMetadata').resolves(); const mockGetLocales = sinon.stub(exportTaxonomies, 'getLocalesToExport').returns(['en-us']); @@ -644,14 +642,16 @@ describe('ExportTaxonomies', () => { }); it('should use locale-based export when supported', async () => { - const mockFetchTaxonomies = sinon.stub(exportTaxonomies, 'fetchTaxonomies').callsFake(async (locale, checkSupport) => { - if (checkSupport) { - exportTaxonomies.isLocaleBasedExportSupported = true; - } - if (locale && typeof locale === 'string' && !exportTaxonomies.taxonomiesByLocale[locale]) { - exportTaxonomies.taxonomiesByLocale[locale] = new Set(['taxonomy-1']); - } - }); + const mockFetchTaxonomies = sinon + .stub(exportTaxonomies, 'fetchTaxonomies') + .callsFake(async (locale, checkSupport) => { + if (checkSupport) { + exportTaxonomies.isLocaleBasedExportSupported = true; + } + if (locale && typeof locale === 'string' && !exportTaxonomies.taxonomiesByLocale[locale]) { + exportTaxonomies.taxonomiesByLocale[locale] = new Set(['taxonomy-1']); + } + }); const mockProcessLocale = sinon.stub(exportTaxonomies, 'processLocaleExport').resolves(); const mockWriteMetadata = sinon.stub(exportTaxonomies, 'writeTaxonomiesMetadata').resolves(); const mockGetLocales = sinon.stub(exportTaxonomies, 'getLocalesToExport').returns(['en-us', 'es-es']); @@ -683,4 +683,3 @@ describe('ExportTaxonomies', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/webhooks.test.ts b/packages/contentstack-export/test/unit/export/modules/webhooks.test.ts index 01235e2de4..4ba9971d72 100644 --- a/packages/contentstack-export/test/unit/export/modules/webhooks.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/webhooks.test.ts @@ -15,15 +15,14 @@ describe('ExportWebhooks', () => { fetchAll: sinon.stub().resolves({ items: [ { uid: 'webhook-1', name: 'Webhook 1' }, - { uid: 'webhook-2', name: 'Webhook 2' } + { uid: 'webhook-2', name: 'Webhook 2' }, ], - count: 2 - }) - }) + count: 2, + }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -39,7 +38,7 @@ describe('ExportWebhooks', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -48,7 +47,7 @@ describe('ExportWebhooks', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -60,22 +59,21 @@ describe('ExportWebhooks', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['webhooks'], webhooks: { dirName: 'webhooks', fileName: 'webhooks.json', limit: 100, - invalidKeys: [] - } - } + invalidKeys: [], + }, + }, } as any; exportWebhooks = new ExportWebhooks({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'webhooks' + moduleName: 'webhooks', }); // Stub FsUtility methods - created once in beforeEach @@ -105,18 +103,18 @@ describe('ExportWebhooks', () => { it('should fetch and process webhooks correctly', async () => { const webhooks = [ { uid: 'webhook-1', name: 'Webhook 1', SYS_ACL: 'test' }, - { uid: 'webhook-2', name: 'Webhook 2', SYS_ACL: 'test' } + { uid: 'webhook-2', name: 'Webhook 2', SYS_ACL: 'test' }, ]; mockStackClient.webhook.returns({ fetchAll: sinon.stub().resolves({ items: webhooks, - count: 2 - }) + count: 2, + }), }); await exportWebhooks.getWebhooks(); - + // Verify webhooks were processed and SYS_ACL was removed expect(Object.keys(exportWebhooks.webhooks).length).to.equal(2); expect(exportWebhooks.webhooks['webhook-1'].SYS_ACL).to.be.undefined; @@ -131,19 +129,19 @@ describe('ExportWebhooks', () => { if (callCount === 1) { return Promise.resolve({ items: Array(100).fill({ uid: `webhook-${callCount}`, name: 'Test' }), - count: 150 + count: 150, }); } else { return Promise.resolve({ items: Array(50).fill({ uid: `webhook-${callCount}`, name: 'Test' }), - count: 150 + count: 150, }); } - }) + }), }); await exportWebhooks.getWebhooks(); - + // Verify multiple calls were made expect(callCount).to.be.greaterThan(1); }); @@ -153,21 +151,21 @@ describe('ExportWebhooks', () => { it('should complete full export flow and write webhooks to file', async () => { const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; const makeDirectoryStub = FsUtility.prototype.makeDirectory as sinon.SinonStub; - + const webhooks = [ { uid: 'webhook-1', name: 'Webhook 1' }, - { uid: 'webhook-2', name: 'Webhook 2' } + { uid: 'webhook-2', name: 'Webhook 2' }, ]; mockStackClient.webhook.returns({ fetchAll: sinon.stub().resolves({ items: webhooks, - count: 2 - }) + count: 2, + }), }); await exportWebhooks.start(); - + // Verify webhooks were processed expect(Object.keys(exportWebhooks.webhooks).length).to.equal(2); expect(exportWebhooks.webhooks['webhook-1']).to.exist; @@ -183,13 +181,13 @@ describe('ExportWebhooks', () => { mockStackClient.webhook.returns({ fetchAll: sinon.stub().resolves({ items: [], - count: 0 - }) + count: 0, + }), }); exportWebhooks.webhooks = {}; await exportWebhooks.start(); - + // Verify writeFile was NOT called when webhooks are empty expect(writeFileStub.called).to.be.false; }); @@ -199,7 +197,7 @@ describe('ExportWebhooks', () => { it('should sanitize webhook attributes and remove SYS_ACL', () => { const webhooks = [ { uid: 'webhook-1', name: 'Webhook 1', SYS_ACL: 'remove' }, - { uid: 'webhook-2', name: 'Webhook 2', SYS_ACL: 'remove' } + { uid: 'webhook-2', name: 'Webhook 2', SYS_ACL: 'remove' }, ]; exportWebhooks.sanitizeAttribs(webhooks); @@ -209,9 +207,7 @@ describe('ExportWebhooks', () => { }); it('should handle webhooks without name field', () => { - const webhooks = [ - { uid: 'webhook-1', SYS_ACL: 'remove' } - ]; + const webhooks = [{ uid: 'webhook-1', SYS_ACL: 'remove' }]; exportWebhooks.sanitizeAttribs(webhooks); @@ -228,4 +224,3 @@ describe('ExportWebhooks', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/export/modules/workflows.test.ts b/packages/contentstack-export/test/unit/export/modules/workflows.test.ts index 59528f9119..6348a0eba2 100644 --- a/packages/contentstack-export/test/unit/export/modules/workflows.test.ts +++ b/packages/contentstack-export/test/unit/export/modules/workflows.test.ts @@ -22,24 +22,23 @@ describe('ExportWorkflows', () => { name: 'Draft', SYS_ACL: { roles: { - uids: [1, 2] - } - } - } + uids: [1, 2], + }, + }, + }, ], - invalidKey: 'remove' - } + invalidKey: 'remove', + }, ], - count: 1 - }) + count: 1, + }), }), role: sinon.stub().returns({ - fetch: sinon.stub().resolves({ uid: 'role-1', name: 'Role 1' }) - }) + fetch: sinon.stub().resolves({ uid: 'role-1', name: 'Role 1' }), + }), }; mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -55,7 +54,7 @@ describe('ExportWorkflows', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -64,7 +63,7 @@ describe('ExportWorkflows', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -76,22 +75,21 @@ describe('ExportWorkflows', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], modules: { types: ['workflows'], workflows: { dirName: 'workflows', fileName: 'workflows.json', limit: 100, - invalidKeys: ['invalidKey'] - } - } + invalidKeys: ['invalidKey'], + }, + }, } as any; exportWorkflows = new ExportWorkflows({ exportConfig: mockExportConfig, stackAPIClient: mockStackClient, - moduleName: 'workflows' + moduleName: 'workflows', }); // Stub FsUtility methods @@ -147,15 +145,15 @@ describe('ExportWorkflows', () => { if (callCount === 1) { return Promise.resolve({ items: new Array(100).fill({ uid: 'test', name: 'Test', workflow_stages: [] as any[] }), - count: 150 + count: 150, }); } else { return Promise.resolve({ items: new Array(50).fill({ uid: 'test2', name: 'Test2', workflow_stages: [] as any[] }), - count: 150 + count: 150, }); } - }) + }), }); await exportWorkflows.getWorkflows(); @@ -166,7 +164,7 @@ describe('ExportWorkflows', () => { it('should handle API errors gracefully without throwing', async () => { mockStackClient.workflow.returns({ - fetchAll: sinon.stub().rejects(new Error('API Error')) + fetchAll: sinon.stub().rejects(new Error('API Error')), }); // Should complete without throwing @@ -177,8 +175,8 @@ describe('ExportWorkflows', () => { mockStackClient.workflow.returns({ fetchAll: sinon.stub().resolves({ items: [], - count: 0 - }) + count: 0, + }), }); const initialCount = Object.keys(exportWorkflows.workflows).length; @@ -192,10 +190,10 @@ describe('ExportWorkflows', () => { mockStackClient.workflow.returns({ fetchAll: sinon.stub().resolves({ items: [{ uid: 'wf-1', name: 'Test' }], - count: 1 - }) + count: 1, + }), }); - + await exportWorkflows.getWorkflows(50); // Verify skip was set in query @@ -210,8 +208,8 @@ describe('ExportWorkflows', () => { uid: 'wf-1', name: 'Workflow 1', invalidKey: 'remove', - workflow_stages: [] as any[] - } + workflow_stages: [] as any[], + }, ]; await exportWorkflows.sanitizeAttribs(workflows); @@ -231,12 +229,12 @@ describe('ExportWorkflows', () => { name: 'Draft', SYS_ACL: { roles: { - uids: [1, 2] - } - } - } - ] - } + uids: [1, 2], + }, + }, + }, + ], + }, ]; await exportWorkflows.sanitizeAttribs(workflows); @@ -250,8 +248,8 @@ describe('ExportWorkflows', () => { { uid: 'wf-1', name: 'Workflow 1', - workflow_stages: [] as any[] - } + workflow_stages: [] as any[], + }, ]; await exportWorkflows.sanitizeAttribs(workflows); @@ -279,7 +277,7 @@ describe('ExportWorkflows', () => { it('should handle API errors gracefully', async () => { mockStackClient.role.returns({ - fetch: sinon.stub().rejects(new Error('API Error')) + fetch: sinon.stub().rejects(new Error('API Error')), }); // Should complete without throwing @@ -305,8 +303,8 @@ describe('ExportWorkflows', () => { mockStackClient.workflow.returns({ fetchAll: sinon.stub().resolves({ items: [], - count: 0 - }) + count: 0, + }), }); const writeFileStub = FsUtility.prototype.writeFile as sinon.SinonStub; @@ -320,7 +318,7 @@ describe('ExportWorkflows', () => { it('should handle errors during export without throwing', async () => { mockStackClient.workflow.returns({ - fetchAll: sinon.stub().rejects(new Error('Export failed')) + fetchAll: sinon.stub().rejects(new Error('Export failed')), }); // Should complete without throwing @@ -328,4 +326,3 @@ describe('ExportWorkflows', () => { }); }); }); - diff --git a/packages/contentstack-export/test/unit/utils/export-config-handler.test.ts b/packages/contentstack-export/test/unit/utils/export-config-handler.test.ts index f03687ef1c..083b9d7973 100644 --- a/packages/contentstack-export/test/unit/utils/export-config-handler.test.ts +++ b/packages/contentstack-export/test/unit/utils/export-config-handler.test.ts @@ -17,19 +17,19 @@ describe('Export Config Handler', () => { beforeEach(() => { sandbox = sinon.createSandbox(); - + // Stub utility functions readFileStub = sandbox.stub(fileHelper, 'readFile').resolves({}); askExportDirStub = sandbox.stub(interactive, 'askExportDir').resolves('/default/export/dir'); askAPIKeyStub = sandbox.stub(interactive, 'askAPIKey').resolves('default-api-key'); loginStub = sandbox.stub(basicLogin, 'default').resolves(); - + // Stub configHandler.get - this controls isAuthenticated() behavior // isAuthenticated() internally calls authHandler.isAuthenticated() which checks // configHandler.get('authorisationType'). Returns 'OAUTH' or 'AUTH' for authenticated configHandlerGetStub = sandbox.stub(utilities.configHandler, 'get'); configHandlerGetStub.returns(undefined); // Default to not authenticated - + // Stub cliux.print sandbox.stub(utilities.cliux, 'print'); }); @@ -43,12 +43,11 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data/path' }; const config = await setupConfig(flags); - + expect(config.exportDir).to.equal(path.resolve('/test/data/path')); - expect(config.data).to.equal(path.resolve('/test/data/path')); expect(askExportDirStub.called).to.be.false; }); @@ -56,10 +55,10 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { 'data-dir': '/test/data-dir/path' }; const config = await setupConfig(flags); - + expect(config.exportDir).to.equal(path.resolve('/test/data-dir/path')); expect(askExportDirStub.called).to.be.false; }); @@ -68,10 +67,10 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = {}; const config = await setupConfig(flags); - + expect(askExportDirStub.called).to.be.true; expect(config.exportDir).to.equal(path.resolve('/default/export/dir')); }); @@ -80,7 +79,7 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'BASIC' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/path*with*special' }; // askExportDirStub will be called when the pattern detects special characters // Need to use callsFake to handle multiple calls - first for the invalid path check, then the re-ask @@ -92,9 +91,9 @@ describe('Export Config Handler', () => { } return Promise.resolve('/valid/path'); }); - + const config = await setupConfig(flags); - + expect((utilities.cliux.print as sinon.SinonStub).called).to.be.true; expect(askExportDirStub.called).to.be.true; // The resolved path from askExportDirStub should be used @@ -105,10 +104,10 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: "'/test/quoted/path'" }; const config = await setupConfig(flags); - + expect(config.exportDir).to.not.include("'"); expect(config.exportDir).to.not.include('"'); }); @@ -119,49 +118,47 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const externalConfig = { - contentVersion: 3, - customField: 'customValue' + customField: 'customValue', }; readFileStub.resolves(externalConfig); - + const flags = { config: '/path/to/config.json', data: '/test/data' }; const config = await setupConfig(flags); - + expect(readFileStub.calledWith('/path/to/config.json')).to.be.true; - expect((config as any).contentVersion).to.equal(3); expect((config as any).customField).to.equal('customValue'); }); + }); describe('Management Token Alias', () => { it('should set management token and API key from alias', async () => { configHandlerGetStub.withArgs('tokens.test-alias').returns({ token: 'test-management-token', - apiKey: 'test-api-key' + apiKey: 'test-api-key', }); - + const flags = { 'management-token-alias': 'test-alias', - data: '/test/data' + data: '/test/data', }; const config = await setupConfig(flags); - + expect(config.management_token).to.equal('test-management-token'); expect(config.apiKey).to.equal('test-api-key'); expect(config.authenticationMethod).to.equal('Management Token'); - expect(config.source_stack).to.equal('test-api-key'); }); it('should throw error when management token not found for alias', async () => { configHandlerGetStub.withArgs('tokens.invalid-alias').returns(undefined); - + const flags = { 'management-token-alias': 'invalid-alias', - data: '/test/data' + data: '/test/data', }; - + try { await setupConfig(flags); expect.fail('Should have thrown an error'); @@ -173,15 +170,15 @@ describe('Export Config Handler', () => { it('should support alias flag as alternative to management-token-alias', async () => { configHandlerGetStub.withArgs('tokens.test-alias').returns({ token: 'test-token', - apiKey: 'test-key' + apiKey: 'test-key', }); - + const flags = { alias: 'test-alias', - data: '/test/data' + data: '/test/data', }; const config = await setupConfig(flags); - + expect(config.management_token).to.equal('test-token'); expect(config.apiKey).to.equal('test-key'); }); @@ -191,19 +188,19 @@ describe('Export Config Handler', () => { it('should use Basic Auth with username and password when not authenticated', async () => { // Make sure isAuthenticated returns false configHandlerGetStub.withArgs('authorisationType').returns(undefined); - + // Provide username and password via external config file readFileStub.resolves({ username: 'test@example.com', - password: 'test-password' + password: 'test-password', }); - - const flags = { + + const flags = { data: '/test/data', - config: '/path/to/config.json' // This triggers readFileStub with username/password + config: '/path/to/config.json', // This triggers readFileStub with username/password }; const config = await setupConfig(flags); - + expect(loginStub.called).to.be.true; expect(config.authenticationMethod).to.equal('Basic Auth'); }); @@ -211,9 +208,9 @@ describe('Export Config Handler', () => { it('should throw error when not authenticated and no credentials provided', async () => { (utilities.configHandler.get as sinon.SinonStub).withArgs('authorisationType').returns(undefined); readFileStub.resolves({}); - + const flags = { data: '/test/data' }; - + try { await setupConfig(flags); expect.fail('Should have thrown an error'); @@ -225,13 +222,13 @@ describe('Export Config Handler', () => { it('should set OAuth authentication method when user is OAuth authenticated', async () => { (utilities.configHandler.get as sinon.SinonStub).withArgs('authorisationType').returns('OAUTH' as any); (utilities.configHandler.get as sinon.SinonStub).withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data', - 'stack-api-key': 'test-api-key' + 'stack-api-key': 'test-api-key', }; const config = await setupConfig(flags); - + expect(config.authenticationMethod).to.equal('OAuth'); expect(config.apiKey).to.equal('test-api-key'); }); @@ -251,13 +248,13 @@ describe('Export Config Handler', () => { // Looking at line 72-79, if isAuthenticated() is true and authorisationType !== 'OAUTH', it's Basic Auth // So we need authorisationType to be 'BASIC' (which makes isAuthenticated true, but not 'OAUTH') configHandlerGetStub.withArgs('authorisationType').returns('BASIC'); - + const flags = { data: '/test/data', - 'stack-api-key': 'test-api-key' + 'stack-api-key': 'test-api-key', }; const config = await setupConfig(flags); - + expect(config.authenticationMethod).to.equal('Basic Auth'); expect(config.apiKey).to.equal('test-api-key'); }); @@ -268,15 +265,14 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data', - 'stack-uid': 'stack-uid-value' + 'stack-uid': 'stack-uid-value', }; const config = await setupConfig(flags); - + expect(config.apiKey).to.equal('stack-uid-value'); - expect(config.source_stack).to.equal('stack-uid-value'); expect(askAPIKeyStub.called).to.be.false; }); @@ -284,31 +280,31 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data', - 'stack-api-key': 'stack-api-key-value' + 'stack-api-key': 'stack-api-key-value', }; const config = await setupConfig(flags); - + expect(config.apiKey).to.equal('stack-api-key-value'); expect(askAPIKeyStub.called).to.be.false; }); - it('should use source_stack from config when available', async () => { + it('should use apiKey from config when available', async () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'BASIC' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - // Provide source_stack via external config file - readFileStub.resolves({ source_stack: 'config-source-stack' }); - - const flags = { + // Provide apiKey via external config file + readFileStub.resolves({ apiKey: 'config-api-key' }); + + const flags = { data: '/test/data', - config: '/path/to/config.json' // This triggers readFileStub with source_stack + config: '/path/to/config.json', // This triggers readFileStub with apiKey }; const config = await setupConfig(flags); - - expect(config.apiKey).to.equal('config-source-stack'); + + expect(config.apiKey).to.equal('config-api-key'); expect(askAPIKeyStub.called).to.be.false; }); @@ -317,10 +313,10 @@ describe('Export Config Handler', () => { // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); readFileStub.resolves({}); - + const flags = { data: '/test/data' }; const config = await setupConfig(flags); - + expect(askAPIKeyStub.called).to.be.true; expect(config.apiKey).to.equal('default-api-key'); }); @@ -329,12 +325,12 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data', - 'stack-api-key': 12345 as any + 'stack-api-key': 12345 as any, }; - + try { await setupConfig(flags); expect.fail('Should have thrown an error'); @@ -348,16 +344,16 @@ describe('Export Config Handler', () => { it('should set forceStopMarketplaceAppsPrompt from yes flag', async () => { configHandlerGetStub.withArgs('tokens.test-alias').returns({ token: 'token', - apiKey: 'key' + apiKey: 'key', }); - + const flags = { 'management-token-alias': 'test-alias', data: '/test/data', - yes: true + yes: true, }; const config = await setupConfig(flags); - + expect(config.forceStopMarketplaceAppsPrompt).to.be.true; }); @@ -365,14 +361,14 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data', 'stack-api-key': 'test-key', - 'branch-alias': 'main-branch' + 'branch-alias': 'main-branch', }; const config = await setupConfig(flags); - + expect(config.branchAlias).to.equal('main-branch'); }); @@ -380,14 +376,14 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data', 'stack-api-key': 'test-key', - branch: 'feature-branch' + branch: 'feature-branch', }; const config = await setupConfig(flags); - + expect(config.branchName).to.equal('feature-branch'); }); @@ -395,14 +391,14 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data', 'stack-api-key': 'test-key', - module: 'assets' + module: 'assets', }; const config = await setupConfig(flags); - + expect(config.moduleName).to.equal('assets'); expect(config.singleModuleExport).to.be.true; }); @@ -411,14 +407,14 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data', 'stack-api-key': 'test-key', - 'secured-assets': true + 'secured-assets': true, }; const config = await setupConfig(flags); - + expect(config.securedAssets).to.be.true; }); @@ -426,14 +422,14 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data', 'stack-api-key': 'test-key', - 'content-types': ['ct-1', 'ct-2'] + 'content-types': ['ct-1', 'ct-2'], }; const config = await setupConfig(flags); - + expect(config.contentTypes).to.deep.equal(['ct-1', 'ct-2']); }); @@ -441,14 +437,14 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data', 'stack-api-key': 'test-key', - 'content-types': [] as string[] + 'content-types': [] as string[], }; const config = await setupConfig(flags); - + expect(config.contentTypes).to.be.undefined; }); }); @@ -458,15 +454,15 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const queryObj = { content_type_uid: 'blog' }; const flags = { data: '/test/data', 'stack-api-key': 'test-key', - query: JSON.stringify(queryObj) + query: JSON.stringify(queryObj), }; const config = await setupConfig(flags); - + expect(config.query).to.deep.equal(queryObj); expect(readFileStub.called).to.be.false; }); @@ -475,17 +471,17 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const queryObj = { content_type_uid: 'blog', locale: 'en-us' }; readFileStub.resolves(queryObj); - + const flags = { data: '/test/data', 'stack-api-key': 'test-key', - query: '/path/to/query.json' + query: '/path/to/query.json', }; const config = await setupConfig(flags); - + expect(readFileStub.calledWith('/path/to/query.json')).to.be.true; expect(config.query).to.deep.equal(queryObj); }); @@ -494,17 +490,17 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const queryObj = { content_type_uid: 'blog' }; readFileStub.resolves(queryObj); - + const flags = { data: '/test/data', 'stack-api-key': 'test-key', - query: '/path/to/query' + query: '/path/to/query', }; const config = await setupConfig(flags); - + expect(readFileStub.called).to.be.true; expect(config.query).to.deep.equal(queryObj); }); @@ -513,13 +509,13 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + const flags = { data: '/test/data', 'stack-api-key': 'test-key', - query: 'invalid json {' + query: 'invalid json {', }; - + try { await setupConfig(flags); expect.fail('Should have thrown an error'); @@ -534,18 +530,18 @@ describe('Export Config Handler', () => { // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - + readFileStub.resolves({ - filteredModules: ['assets', 'content-types'] + filteredModules: ['assets', 'content-types'], }); - + const flags = { data: '/test/data', 'stack-api-key': 'test-key', - config: '/path/to/config.json' + config: '/path/to/config.json', }; const config = await setupConfig(flags); - + expect(config.modules.types).to.include('assets'); expect(config.modules.types).to.include('content-types'); // Should not include modules not in filteredModules @@ -559,31 +555,17 @@ describe('Export Config Handler', () => { // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); configHandlerGetStub.withArgs('authtoken').returns('auth-token-value'); - + const flags = { data: '/test/data', - 'stack-api-key': 'test-key' + 'stack-api-key': 'test-key', }; const config = await setupConfig(flags); - + expect(config.auth_token).to.equal('auth-token-value'); // Verify isAuthenticated was called by checking config.isAuthenticated was set expect((utilities.configHandler.get as sinon.SinonStub).called).to.be.true; }); - it('should set source_stack equal to apiKey', async () => { - // Set authenticated: isAuthenticated() checks configHandler.get('authorisationType') - // Returns 'OAUTH' or 'AUTH' for authenticated, undefined for not authenticated - configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); - - const flags = { - data: '/test/data', - 'stack-api-key': 'test-api-key' - }; - const config = await setupConfig(flags); - - expect(config.source_stack).to.equal(config.apiKey); - expect(config.source_stack).to.equal('test-api-key'); - }); }); -}); \ No newline at end of file +}); diff --git a/packages/contentstack-export/test/unit/utils/logger.test.ts b/packages/contentstack-export/test/unit/utils/logger.test.ts index 9e973037f5..b684951eb2 100644 --- a/packages/contentstack-export/test/unit/utils/logger.test.ts +++ b/packages/contentstack-export/test/unit/utils/logger.test.ts @@ -11,9 +11,8 @@ describe('Logger', () => { beforeEach(() => { sandbox = sinon.createSandbox(); - + mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, @@ -30,7 +29,7 @@ describe('Logger', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, forceStopMarketplaceAppsPrompt: false, master_locale: { code: 'en-us' }, @@ -38,7 +37,7 @@ describe('Logger', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -50,8 +49,7 @@ describe('Logger', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: '', - onlyTSModules: [], - modules: {} + modules: {}, } as any; }); @@ -65,7 +63,7 @@ describe('Logger', () => { it('should log message when type is not error', async () => { // Should complete without throwing await loggerModule.log(mockExportConfig, 'Test message', 'info'); - + // Verify function completed successfully expect(true).to.be.true; // Basic assertion that function executed }); @@ -73,7 +71,7 @@ describe('Logger', () => { it('should log error message when type is error', async () => { // Should complete without throwing await loggerModule.log(mockExportConfig, 'Error message', 'error'); - + // Verify function completed successfully expect(true).to.be.true; // Basic assertion that function executed }); @@ -81,37 +79,37 @@ describe('Logger', () => { it('should use cliLogsPath when available', async () => { // Should complete without throwing await loggerModule.log(mockExportConfig, 'Test', 'info'); - + // Verify function completed successfully expect(true).to.be.true; }); it('should fallback to data path when cliLogsPath is not available', async () => { const configWithoutLogsPath = { ...mockExportConfig, cliLogsPath: undefined as any }; - + // Should complete without throwing await loggerModule.log(configWithoutLogsPath, 'Test', 'info'); - + // Verify function completed successfully expect(true).to.be.true; }); it('should handle object arguments in log message', async () => { const testObject = { key: 'value', message: 'test' }; - + // Should complete without throwing await loggerModule.log(mockExportConfig, testObject, 'info'); - + // Verify function completed successfully expect(true).to.be.true; }); it('should remove ANSI escape codes from log messages', async () => { const ansiMessage = '\u001B[31mRed text\u001B[0m'; - + // Should complete without throwing await loggerModule.log(mockExportConfig, ansiMessage, 'info'); - + // Verify function completed successfully expect(true).to.be.true; }); @@ -119,7 +117,7 @@ describe('Logger', () => { it('should handle null message arguments', async () => { // Should complete without throwing await loggerModule.log(mockExportConfig, null as any, 'info'); - + // Verify function completed successfully expect(true).to.be.true; }); @@ -127,7 +125,7 @@ describe('Logger', () => { it('should handle undefined message arguments', async () => { // Should complete without throwing await loggerModule.log(mockExportConfig, undefined as any, 'info'); - + // Verify function completed successfully expect(true).to.be.true; }); @@ -142,7 +140,7 @@ describe('Logger', () => { it('should remove file transports after logger is initialized', async () => { // Initialize logger by calling log await loggerModule.log(mockExportConfig, 'init', 'info'); - + // Should not throw when removing file transports expect(() => loggerModule.unlinkFileLogger()).to.not.throw(); }); @@ -150,7 +148,7 @@ describe('Logger', () => { it('should handle multiple calls gracefully', async () => { // Initialize logger await loggerModule.log(mockExportConfig, 'init', 'info'); - + // Should handle multiple calls loggerModule.unlinkFileLogger(); expect(() => loggerModule.unlinkFileLogger()).to.not.throw(); @@ -162,7 +160,7 @@ describe('Logger', () => { // Test all log types await loggerModule.log(mockExportConfig, 'Info message', 'info'); await loggerModule.log(mockExportConfig, 'Error message', 'error'); - + // Verify all completed successfully expect(true).to.be.true; }); @@ -173,13 +171,13 @@ describe('Logger', () => { data: 'value', array: [1, 2, 3], nullValue: null as any, - undefinedValue: undefined as any - } + undefinedValue: undefined as any, + }, }; - + // Should complete without throwing await loggerModule.log(mockExportConfig, complexObject, 'info'); - + // Verify function completed successfully expect(true).to.be.true; }); @@ -187,17 +185,17 @@ describe('Logger', () => { it('should handle empty string messages', async () => { // Should complete without throwing await loggerModule.log(mockExportConfig, '', 'info'); - + // Verify function completed successfully expect(true).to.be.true; }); it('should handle very long messages', async () => { const longMessage = 'A'.repeat(10); - + // Should complete without throwing await loggerModule.log(mockExportConfig, longMessage, 'info'); - + // Verify function completed successfully expect(true).to.be.true; }); diff --git a/packages/contentstack-export/test/unit/utils/marketplace-app-helper.test.ts b/packages/contentstack-export/test/unit/utils/marketplace-app-helper.test.ts index 561b2673fa..d1a9e2170d 100644 --- a/packages/contentstack-export/test/unit/utils/marketplace-app-helper.test.ts +++ b/packages/contentstack-export/test/unit/utils/marketplace-app-helper.test.ts @@ -12,15 +12,13 @@ describe('Marketplace App Helper Utils', () => { sandbox = sinon.createSandbox(); mockExportConfig = { - contentVersion: 1, versioning: false, host: 'https://api.contentstack.io', developerHubUrls: {}, - apiKey: 'test-api-key', + apiKey: 'test-stack-uid', exportDir: '/test/export', data: '/test/data', branchName: '', - source_stack: 'test-stack-uid', context: { command: 'cm:stacks:export', module: 'marketplace-apps', @@ -29,7 +27,7 @@ describe('Marketplace App Helper Utils', () => { sessionId: 'session-123', apiKey: 'test-api-key', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, cliLogsPath: '/test/logs', forceStopMarketplaceAppsPrompt: false, @@ -38,7 +36,7 @@ describe('Marketplace App Helper Utils', () => { name: 'us', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, skipStackSettings: false, skipDependencies: false, @@ -50,14 +48,13 @@ describe('Marketplace App Helper Utils', () => { writeConcurrency: 5, developerHubBaseUrl: '', marketplaceAppEncryptionKey: 'test-encryption-key', - onlyTSModules: [], modules: { types: ['marketplace-apps'], marketplace_apps: { dirName: 'marketplace-apps', - fileName: 'marketplace-apps.json' - } - } + fileName: 'marketplace-apps.json', + }, + }, } as any; }); @@ -78,7 +75,7 @@ describe('Marketplace App Helper Utils', () => { it('should handle different host URLs', async () => { mockExportConfig.host = 'https://eu-api.contentstack.com'; - + const result = await getDeveloperHubUrl(mockExportConfig); // Should return a URL based on the host @@ -99,13 +96,13 @@ describe('Marketplace App Helper Utils', () => { const mockStackData = { org_uid: 'test-org-uid-123', name: 'Test Stack', - uid: 'stack-uid' + uid: 'stack-uid', }; const mockFetch = sandbox.stub().resolves(mockStackData); const mockStack = sandbox.stub().returns({ fetch: mockFetch }); const mockAPIClient = { - stack: mockStack + stack: mockStack, }; // Use replaceGetter since managementSDKClient is a getter @@ -124,8 +121,8 @@ describe('Marketplace App Helper Utils', () => { expect(result).to.equal('test-org-uid-123'); }); - it('should use source_stack from config as api_key', async () => { - mockExportConfig.source_stack = 'custom-stack-key'; + it('should use apiKey from config as api_key', async () => { + mockExportConfig.apiKey = 'custom-stack-key'; const mockStackData = { org_uid: 'org-123' }; const mockFetch = sandbox.stub().resolves(mockStackData); @@ -174,7 +171,7 @@ describe('Marketplace App Helper Utils', () => { it('should return undefined when stack data has no org_uid', async () => { const mockStackData = { name: 'Test Stack', - uid: 'stack-uid' + uid: 'stack-uid', // No org_uid property }; @@ -267,7 +264,11 @@ describe('Marketplace App Helper Utils', () => { const inquireStub = sandbox.stub(utilities.cliux, 'inquire').resolves('user-key'); - sandbox.replaceGetter(utilities, 'NodeCrypto', () => sandbox.fake.returns({ encrypt: sandbox.stub() } as any) as any); + sandbox.replaceGetter( + utilities, + 'NodeCrypto', + () => sandbox.fake.returns({ encrypt: sandbox.stub() } as any) as any, + ); await createNodeCryptoInstance(mockExportConfig); @@ -286,11 +287,15 @@ describe('Marketplace App Helper Utils', () => { // Non-empty strings should return true (validation doesn't trim) expect(opts.validate('valid-key')).to.equal(true); expect(opts.validate('another-valid-key-123')).to.equal(true); - + return 'valid-key'; }); - sandbox.replaceGetter(utilities, 'NodeCrypto', () => sandbox.fake.returns({ encrypt: sandbox.stub() } as any) as any); + sandbox.replaceGetter( + utilities, + 'NodeCrypto', + () => sandbox.fake.returns({ encrypt: sandbox.stub() } as any) as any, + ); await createNodeCryptoInstance(mockExportConfig); @@ -335,7 +340,11 @@ describe('Marketplace App Helper Utils', () => { const inquireStub = sandbox.stub(utilities.cliux, 'inquire').resolves('prompted-key'); - sandbox.replaceGetter(utilities, 'NodeCrypto', () => sandbox.fake.returns({ encrypt: sandbox.stub() } as any) as any); + sandbox.replaceGetter( + utilities, + 'NodeCrypto', + () => sandbox.fake.returns({ encrypt: sandbox.stub() } as any) as any, + ); await createNodeCryptoInstance(mockExportConfig); @@ -348,7 +357,7 @@ describe('Marketplace App Helper Utils', () => { mockExportConfig.marketplaceAppEncryptionKey = 'test-key'; const mockNodeCrypto = { - encrypt: sandbox.stub().returns('encrypted-data') + encrypt: sandbox.stub().returns('encrypted-data'), }; sandbox.replaceGetter(utilities, 'NodeCrypto', () => sandbox.fake.returns(mockNodeCrypto) as any); @@ -365,7 +374,11 @@ describe('Marketplace App Helper Utils', () => { const inquireStub = sandbox.stub(utilities.cliux, 'inquire'); - sandbox.replaceGetter(utilities, 'NodeCrypto', () => sandbox.fake.returns({ encrypt: sandbox.stub() } as any) as any); + sandbox.replaceGetter( + utilities, + 'NodeCrypto', + () => sandbox.fake.returns({ encrypt: sandbox.stub() } as any) as any, + ); await createNodeCryptoInstance(mockExportConfig); @@ -373,4 +386,3 @@ describe('Marketplace App Helper Utils', () => { }); }); }); - diff --git a/packages/contentstack-import/README.md b/packages/contentstack-import/README.md index e894670358..5b3f75b7b1 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/2.0.0-beta.3 darwin-arm64 node-v24.12.0 +@contentstack/cli-cm-import/2.0.0-beta.4 darwin-arm64 node-v24.12.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND diff --git a/packages/contentstack-import/package.json b/packages/contentstack-import/package.json index 78bf5110e2..3523f0eb4a 100644 --- a/packages/contentstack-import/package.json +++ b/packages/contentstack-import/package.json @@ -1,15 +1,15 @@ { "name": "@contentstack/cli-cm-import", "description": "Contentstack CLI plugin to import content into stack", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "author": "Contentstack", "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { "@contentstack/cli-audit": "~2.0.0-beta.1", "@contentstack/cli-command": "~1.7.0", "@contentstack/cli-utilities": "~1.15.0", - "@contentstack/management": "~1.22.0", - "@contentstack/cli-variants": "~2.0.0-beta.3", + "@contentstack/management": "~1.27.2", + "@contentstack/cli-variants": "~2.0.0-beta.4", "@oclif/core": "^4.3.0", "big-json": "^3.2.0", "bluebird": "^3.7.2", @@ -91,4 +91,4 @@ } }, "repository": "https://github.com/contentstack/cli" -} +} \ No newline at end of file diff --git a/packages/contentstack-import/src/commands/cm/stacks/import.ts b/packages/contentstack-import/src/commands/cm/stacks/import.ts index 79d84d17fe..dce995fff3 100644 --- a/packages/contentstack-import/src/commands/cm/stacks/import.ts +++ b/packages/contentstack-import/src/commands/cm/stacks/import.ts @@ -148,14 +148,7 @@ export default class ImportCommand extends Command { const moduleImporter = new ModuleImporter(managementAPIClient, importConfig); const result = await moduleImporter.start(); backupDir = importConfig.backupDir; - - if (!result?.noSuccessMsg) { - const successMessage = importConfig.stackName - ? `Successfully imported the content to the stack named ${importConfig.stackName} with the API key ${importConfig.apiKey} .` - : `The content has been imported to the stack ${importConfig.apiKey} successfully!`; - log.success(successMessage, importConfig.context); - } - + //Note: Final summary is now handled by summary manager CLIProgressManager.printGlobalSummary(); this.logSuccessAndBackupMessages(backupDir, importConfig); // Clear progress module setting now that import is complete diff --git a/packages/contentstack-import/src/import/module-importer.ts b/packages/contentstack-import/src/import/module-importer.ts index a83aaf0301..ae6d024468 100755 --- a/packages/contentstack-import/src/import/module-importer.ts +++ b/packages/contentstack-import/src/import/module-importer.ts @@ -46,8 +46,6 @@ class ModuleImporter { const backupDir = await backupHandler(this.importConfig); if (backupDir) { this.importConfig.backupDir = backupDir; - // To support the old config - this.importConfig.data = backupDir; } // NOTE audit and fix the import content. @@ -86,17 +84,7 @@ class ModuleImporter { async importByModuleByName(moduleName: Modules) { log.info(`Starting import of ${moduleName} module`, this.importConfig.context); - - // Check if module should be skipped for legacy contentVersion - if (this.importConfig.contentVersion !== 2) { - const onlyTSModules = this.importConfig.onlyTSModules || []; - if (onlyTSModules.includes(moduleName)) { - // Module is in onlyTSModules list, skip import for legacy contentVersion - return undefined; - } - } - - // Use module import (same for both contentVersion 1 and 2) + return startModuleImport({ stackAPIClient: this.stackAPIClient, importConfig: this.importConfig, diff --git a/packages/contentstack-import/src/import/modules/content-types.ts b/packages/contentstack-import/src/import/modules/content-types.ts index bb82baaf02..04ba1041ca 100644 --- a/packages/contentstack-import/src/import/modules/content-types.ts +++ b/packages/contentstack-import/src/import/modules/content-types.ts @@ -61,19 +61,19 @@ export default class ContentTypesImport extends BaseClass { this.cTsConfig = importConfig.modules['content-types']; this.gFsConfig = importConfig.modules['global-fields']; this.reqConcurrency = this.cTsConfig.writeConcurrency || this.importConfig.writeConcurrency; - this.cTsFolderPath = path.join(sanitizePath(this.importConfig.data), sanitizePath(this.cTsConfig.dirName)); - this.cTsMapperPath = path.join(sanitizePath(this.importConfig.data), 'mapper', 'content_types'); - this.cTsSuccessPath = path.join(sanitizePath(this.importConfig.data), 'mapper', 'content_types', 'success.json'); - this.gFsFolderPath = path.resolve(sanitizePath(this.importConfig.data), sanitizePath(this.gFsConfig.dirName)); - this.gFsMapperFolderPath = path.join(sanitizePath(importConfig.data), 'mapper', 'global_fields', 'success.json'); + this.cTsFolderPath = path.join(sanitizePath(this.importConfig.contentDir), sanitizePath(this.cTsConfig.dirName)); + this.cTsMapperPath = path.join(sanitizePath(this.importConfig.contentDir), 'mapper', 'content_types'); + this.cTsSuccessPath = path.join(sanitizePath(this.importConfig.contentDir), 'mapper', 'content_types', 'success.json'); + this.gFsFolderPath = path.resolve(sanitizePath(this.importConfig.contentDir), sanitizePath(this.gFsConfig.dirName)); + this.gFsMapperFolderPath = path.join(sanitizePath(importConfig.contentDir), 'mapper', 'global_fields', 'success.json'); this.gFsPendingPath = path.join( - sanitizePath(importConfig.data), + sanitizePath(importConfig.contentDir), 'mapper', 'global_fields', 'pending_global_fields.js', ); this.marketplaceAppMapperPath = path.join( - sanitizePath(this.importConfig.data), + sanitizePath(this.importConfig.contentDir), 'mapper', 'marketplace_apps', 'uid-mapping.json', @@ -92,8 +92,8 @@ export default class ContentTypesImport extends BaseClass { this.createdGFs = []; this.pendingGFs = []; this.pendingExts = []; - this.taxonomiesPath = path.join(sanitizePath(importConfig.data), 'mapper', 'taxonomies', 'success.json'); - this.extPendingPath = path.join(sanitizePath(importConfig.data), 'mapper', 'extensions', 'pending_extensions.js'); + this.taxonomiesPath = path.join(sanitizePath(importConfig.contentDir), 'mapper', 'taxonomies', 'success.json'); + this.extPendingPath = path.join(sanitizePath(importConfig.contentDir), 'mapper', 'extensions', 'pending_extensions.js'); } async start(): Promise { diff --git a/packages/contentstack-import/src/import/modules/entries.ts b/packages/contentstack-import/src/import/modules/entries.ts index beeee5a90b..3b5f050f3c 100644 --- a/packages/contentstack-import/src/import/modules/entries.ts +++ b/packages/contentstack-import/src/import/modules/entries.ts @@ -66,34 +66,34 @@ export default class EntriesImport extends BaseClass { super({ importConfig, stackAPIClient }); this.importConfig.context.module = MODULE_CONTEXTS.ENTRIES; this.currentModuleName = MODULE_NAMES[MODULE_CONTEXTS.ENTRIES]; - this.assetUidMapperPath = path.resolve(sanitizePath(importConfig.data), 'mapper', 'assets', 'uid-mapping.json'); - this.assetUrlMapperPath = path.resolve(sanitizePath(importConfig.data), 'mapper', 'assets', 'url-mapping.json'); - this.entriesMapperPath = path.resolve(sanitizePath(importConfig.data), 'mapper', 'entries'); - this.envPath = path.resolve(sanitizePath(importConfig.data), 'environments', 'environments.json'); + this.assetUidMapperPath = path.resolve(sanitizePath(importConfig.contentDir), 'mapper', 'assets', 'uid-mapping.json'); + this.assetUrlMapperPath = path.resolve(sanitizePath(importConfig.contentDir), 'mapper', 'assets', 'url-mapping.json'); + this.entriesMapperPath = path.resolve(sanitizePath(importConfig.contentDir), 'mapper', 'entries'); + this.envPath = path.resolve(sanitizePath(importConfig.contentDir), 'environments', 'environments.json'); this.entriesUIDMapperPath = path.join(sanitizePath(this.entriesMapperPath), 'uid-mapping.json'); this.uniqueUidMapperPath = path.join(sanitizePath(this.entriesMapperPath), 'unique-mapping.json'); this.modifiedCTsPath = path.join(sanitizePath(this.entriesMapperPath), 'modified-schemas.json'); this.marketplaceAppMapperPath = path.join( - sanitizePath(this.importConfig.data), + sanitizePath(this.importConfig.contentDir), 'mapper', 'marketplace_apps', 'uid-mapping.json', ); this.taxonomiesPath = path.join( - sanitizePath(this.importConfig.data), + sanitizePath(this.importConfig.contentDir), 'mapper', 'taxonomies', 'terms', 'success.json', ); this.entriesConfig = importConfig.modules.entries; - this.entriesPath = path.resolve(sanitizePath(importConfig.data), sanitizePath(this.entriesConfig.dirName)); + this.entriesPath = path.resolve(sanitizePath(importConfig.contentDir), sanitizePath(this.entriesConfig.dirName)); this.cTsPath = path.resolve( - sanitizePath(importConfig.data), + sanitizePath(importConfig.contentDir), sanitizePath(importConfig.modules['content-types'].dirName), ); this.localesPath = path.resolve( - sanitizePath(importConfig.data), + sanitizePath(importConfig.contentDir), sanitizePath(importConfig.modules.locales.dirName), sanitizePath(importConfig.modules.locales.fileName), ); diff --git a/packages/contentstack-import/src/import/modules/global-fields.ts b/packages/contentstack-import/src/import/modules/global-fields.ts index bc13201eaa..129ef19fa0 100644 --- a/packages/contentstack-import/src/import/modules/global-fields.ts +++ b/packages/contentstack-import/src/import/modules/global-fields.ts @@ -63,19 +63,19 @@ export default class ImportGlobalFields extends BaseClass { this.pendingGFs = []; this.existingGFs = []; this.reqConcurrency = this.gFsConfig.writeConcurrency || this.config.writeConcurrency; - this.gFsMapperPath = path.resolve(sanitizePath(this.config.data), 'mapper', 'global_fields'); - this.gFsFolderPath = path.resolve(sanitizePath(this.config.data), sanitizePath(this.gFsConfig.dirName)); - this.gFsFailsPath = path.resolve(sanitizePath(this.config.data), 'mapper', 'global_fields', 'fails.json'); - this.gFsSuccessPath = path.resolve(sanitizePath(this.config.data), 'mapper', 'global_fields', 'success.json'); - this.gFsUidMapperPath = path.resolve(sanitizePath(this.config.data), 'mapper', 'global_fields', 'uid-mapping.json'); + this.gFsMapperPath = path.resolve(sanitizePath(this.config.contentDir), 'mapper', 'global_fields'); + this.gFsFolderPath = path.resolve(sanitizePath(this.config.contentDir), sanitizePath(this.gFsConfig.dirName)); + this.gFsFailsPath = path.resolve(sanitizePath(this.config.contentDir), 'mapper', 'global_fields', 'fails.json'); + this.gFsSuccessPath = path.resolve(sanitizePath(this.config.contentDir), 'mapper', 'global_fields', 'success.json'); + this.gFsUidMapperPath = path.resolve(sanitizePath(this.config.contentDir), 'mapper', 'global_fields', 'uid-mapping.json'); this.gFsPendingPath = path.resolve( - sanitizePath(this.config.data), + sanitizePath(this.config.contentDir), 'mapper', 'global_fields', 'pending_global_fields.js', ); this.marketplaceAppMapperPath = path.join( - sanitizePath(this.config.data), + sanitizePath(this.config.contentDir), 'mapper', 'marketplace_apps', 'uid-mapping.json', diff --git a/packages/contentstack-import/src/import/modules/locales.ts b/packages/contentstack-import/src/import/modules/locales.ts index a7c3bc4ee1..6f0790e94b 100644 --- a/packages/contentstack-import/src/import/modules/locales.ts +++ b/packages/contentstack-import/src/import/modules/locales.ts @@ -60,11 +60,11 @@ export default class ImportLocales extends BaseClass { this.createdLocales = []; this.failedLocales = []; this.reqConcurrency = this.localeConfig.writeConcurrency || this.config.writeConcurrency; - this.langMapperPath = path.resolve(sanitizePath(this.config.data), 'mapper', 'languages'); - this.langFolderPath = path.resolve(sanitizePath(this.config.data), sanitizePath(this.localeConfig.dirName)); - this.langFailsPath = path.resolve(sanitizePath(this.config.data), 'mapper', 'languages', 'fails.json'); - this.langSuccessPath = path.resolve(sanitizePath(this.config.data), 'mapper', 'languages', 'success.json'); - this.langUidMapperPath = path.resolve(sanitizePath(this.config.data), 'mapper', 'languages', 'uid-mapper.json'); + this.langMapperPath = path.resolve(sanitizePath(this.config.contentDir), 'mapper', 'languages'); + this.langFolderPath = path.resolve(sanitizePath(this.config.contentDir), sanitizePath(this.localeConfig.dirName)); + this.langFailsPath = path.resolve(sanitizePath(this.config.contentDir), 'mapper', 'languages', 'fails.json'); + this.langSuccessPath = path.resolve(sanitizePath(this.config.contentDir), 'mapper', 'languages', 'success.json'); + this.langUidMapperPath = path.resolve(sanitizePath(this.config.contentDir), 'mapper', 'languages', 'uid-mapper.json'); } async start(): Promise { diff --git a/packages/contentstack-import/src/import/modules/marketplace-apps.ts b/packages/contentstack-import/src/import/modules/marketplace-apps.ts index 46b8daf3c3..6b0049d06a 100644 --- a/packages/contentstack-import/src/import/modules/marketplace-apps.ts +++ b/packages/contentstack-import/src/import/modules/marketplace-apps.ts @@ -454,12 +454,12 @@ export default class ImportMarketplaceApps extends BaseClass { */ async installApp(config: ImportConfig, appManifestUid?: string): Promise { log.debug(`Installing app with manifest UID: ${appManifestUid}`, this.importConfig.context); - log.debug(`Target stack: ${config.target_stack}`, this.importConfig.context); + log.debug(`Target stack: ${config.apiKey}`, this.importConfig.context); return await this.appSdk .marketplace(this.importConfig.org_uid) .app(appManifestUid) - .install({ targetUid: config.target_stack, targetType: 'stack' }) + .install({ targetUid: config.apiKey, targetType: 'stack' }) .then((response) => { log.debug(`App installation successful: ${appManifestUid}`, this.importConfig.context); return response; diff --git a/packages/contentstack-import/src/import/modules/personalize.ts b/packages/contentstack-import/src/import/modules/personalize.ts index 2db4f7741b..711d80ba94 100644 --- a/packages/contentstack-import/src/import/modules/personalize.ts +++ b/packages/contentstack-import/src/import/modules/personalize.ts @@ -164,7 +164,7 @@ export default class ImportPersonalize extends BaseClass { const personalize = this.config.modules.personalize; const { dirName, fileName } = personalize.projects; const projectPath = join( - sanitizePath(this.config.data), + sanitizePath(this.config.contentDir), sanitizePath(personalize.dirName), sanitizePath(dirName), sanitizePath(fileName), diff --git a/packages/contentstack-import/src/import/modules/variant-entries.ts b/packages/contentstack-import/src/import/modules/variant-entries.ts index 8b37532ad0..84617c89f8 100644 --- a/packages/contentstack-import/src/import/modules/variant-entries.ts +++ b/packages/contentstack-import/src/import/modules/variant-entries.ts @@ -29,7 +29,7 @@ export default class ImportVariantEntries extends BaseClass { this.currentModuleName = MODULE_NAMES[MODULE_CONTEXTS.VARIANT_ENTRIES]; this.personalize = importConfig.modules.personalize; this.projectMapperFilePath = path.resolve( - sanitizePath(this.config.data), + sanitizePath(this.config.contentDir), 'mapper', sanitizePath(this.personalize.dirName), 'projects', @@ -133,7 +133,7 @@ export default class ImportVariantEntries extends BaseClass { // Basic validation - check if data file exists const dataFilePath = path.resolve( - sanitizePath(this.config.data), + sanitizePath(this.config.contentDir), 'mapper', 'entries', 'data-for-variant-entry.json', diff --git a/packages/contentstack-import/src/types/import-config.ts b/packages/contentstack-import/src/types/import-config.ts index c00614a8ad..86db5668d1 100644 --- a/packages/contentstack-import/src/types/import-config.ts +++ b/packages/contentstack-import/src/types/import-config.ts @@ -50,7 +50,6 @@ export default interface ImportConfig extends DefaultConfig, ExternalConfig { authtoken?: string; destinationStackName?: string; org_uid?: string; - contentVersion: number; replaceExisting?: boolean; skipExisting?: boolean; skipAudit?: boolean; @@ -59,7 +58,6 @@ export default interface ImportConfig extends DefaultConfig, ExternalConfig { personalizeProjectName?: string; 'exclude-global-modules': false; context: Context; - onlyTSModules?: Modules[]; } type branch = { diff --git a/packages/contentstack-import/src/utils/asset-helper.ts b/packages/contentstack-import/src/utils/asset-helper.ts index 2c8272e90e..0f459dc4c3 100644 --- a/packages/contentstack-import/src/utils/asset-helper.ts +++ b/packages/contentstack-import/src/utils/asset-helper.ts @@ -37,7 +37,7 @@ export const uploadAssetHelper = function (config: ImportConfig, req: any, fsPat req.upload = fsPath; const stackAPIClient = APIClient.stack({ - api_key: config.target_stack, + api_key: config.apiKey, management_token: config.management_token, }); diff --git a/packages/contentstack-import/src/utils/common-helper.ts b/packages/contentstack-import/src/utils/common-helper.ts index c3c21608a2..ad79604691 100644 --- a/packages/contentstack-import/src/utils/common-helper.ts +++ b/packages/contentstack-import/src/utils/common-helper.ts @@ -28,14 +28,14 @@ export const initialization = (configData: ImportConfig) => { export const validateConfig = (importConfig: ImportConfig) => { log.debug('Validating import configuration'); - if (importConfig.email && importConfig.password && !importConfig.target_stack) { + if (importConfig.email && importConfig.password && !importConfig.apiKey) { log.debug('Target stack API token is required when using email/password authentication'); return 'error'; } else if ( !importConfig.email && !importConfig.password && !importConfig.management_token && - importConfig.target_stack && + importConfig.apiKey && !isAuthenticated() ) { log.debug('Authentication credentials missing - either management token or email/password required'); @@ -78,7 +78,7 @@ export const sanitizeStack = (importConfig: ImportConfig) => { log.debug(`New stack version: ${newStackVersion} (${newStackDate})`); const stackFilePath = path.join( - sanitizePath(importConfig.data), + sanitizePath(importConfig.contentDir), sanitizePath(importConfig.modules.stack.dirName), sanitizePath(importConfig.modules.stack.fileName), ); @@ -161,7 +161,7 @@ export const field_rules_update = (importConfig: ImportConfig, ctPath: string) = if (schema.field_rules[k].conditions[i].operand_field === 'reference') { log.debug(`Processing reference field rule condition`); - let entryMapperPath = path.resolve(importConfig.data, 'mapper', 'entries'); + let entryMapperPath = path.resolve(importConfig.contentDir, 'mapper', 'entries'); let entryUidMapperPath = path.join(entryMapperPath, 'uid-mapping.json'); let fieldRulesValue = schema.field_rules[k].conditions[i].value; let fieldRulesArray = fieldRulesValue.split('.'); @@ -184,7 +184,7 @@ export const field_rules_update = (importConfig: ImportConfig, ctPath: string) = } const stackAPIClient = client.stack({ - api_key: importConfig.target_stack, + api_key: importConfig.apiKey, management_token: importConfig.management_token, }); let ctObj = stackAPIClient.contentType(schema.uid); diff --git a/packages/contentstack-import/src/utils/import-config-handler.ts b/packages/contentstack-import/src/utils/import-config-handler.ts index 1ae17ef27a..f6604d0530 100644 --- a/packages/contentstack-import/src/utils/import-config-handler.ts +++ b/packages/contentstack-import/src/utils/import-config-handler.ts @@ -3,7 +3,7 @@ import * as path from 'path'; import { omit, filter, includes, isArray } from 'lodash'; import { configHandler, isAuthenticated, cliux, sanitizePath, log } from '@contentstack/cli-utilities'; import defaultConfig from '../config'; -import { readFile, fileExistsSync } from './file-helper'; +import { readFile } from './file-helper'; import { askContentDir, askAPIKey } from './interactive'; import login from './login-handler'; import { ImportConfig } from '../types'; @@ -20,6 +20,8 @@ const setupConfig = async (importCmdFlags: any): Promise => { // setup the config if (importCmdFlags['config']) { let externalConfig = await readFile(importCmdFlags['config']); + + if (isArray(externalConfig['modules'])) { config.modules.types = filter(config.modules.types, (module) => includes(externalConfig['modules'], module)); externalConfig = omit(externalConfig, ['modules']); @@ -28,7 +30,7 @@ const setupConfig = async (importCmdFlags: any): Promise => { } config.contentDir = sanitizePath( - importCmdFlags['data'] || importCmdFlags['data-dir'] || config.data || (await askContentDir()), + importCmdFlags['data'] || importCmdFlags['data-dir'] || config.contentDir || (await askContentDir()), ); const pattern = /[*$%#<>{}!&?]/g; if (pattern.test(config.contentDir)) { @@ -39,8 +41,6 @@ const setupConfig = async (importCmdFlags: any): Promise => { } config.contentDir = config.contentDir.replace(/['"]/g, ''); config.contentDir = path.resolve(config.contentDir); - //Note to support the old key - config.data = config.contentDir; const managementTokenAlias = importCmdFlags['management-token-alias'] || importCmdFlags['alias']; @@ -78,7 +78,7 @@ const setupConfig = async (importCmdFlags: any): Promise => { log.debug('User authenticated via auth token'); } config.apiKey = - importCmdFlags['stack-uid'] || importCmdFlags['stack-api-key'] || config.target_stack || (await askAPIKey()); + importCmdFlags['stack-uid'] || importCmdFlags['stack-api-key'] || config.apiKey || (await askAPIKey()); if (typeof config.apiKey !== 'string') { throw new Error('Invalid API key received'); } @@ -88,9 +88,6 @@ const setupConfig = async (importCmdFlags: any): Promise => { config.isAuthenticated = isAuthenticated(); config.auth_token = configHandler.get('authtoken'); // TBD handle auth token in httpClient & sdk - //Note to support the old key - config.source_stack = config.apiKey; - config.skipAudit = importCmdFlags['skip-audit']; config.forceStopMarketplaceAppsPrompt = importCmdFlags.yes; config.importWebhookStatus = importCmdFlags['import-webhook-status']; @@ -120,9 +117,6 @@ const setupConfig = async (importCmdFlags: any): Promise => { config.skipEntriesPublish = importCmdFlags['skip-entries-publish']; } - // Note to support old modules - config.target_stack = config.apiKey; - config.replaceExisting = importCmdFlags['replace-existing']; config.skipExisting = importCmdFlags['skip-existing']; diff --git a/packages/contentstack-import/src/utils/import-path-resolver.ts b/packages/contentstack-import/src/utils/import-path-resolver.ts index 16fd7a77c5..2bb5b921f5 100644 --- a/packages/contentstack-import/src/utils/import-path-resolver.ts +++ b/packages/contentstack-import/src/utils/import-path-resolver.ts @@ -70,7 +70,7 @@ export const selectBranchFromDirectory = async (contentDir: string): Promise<{ b export const resolveImportPath = async (importConfig: ImportConfig, stackAPIClient: any): Promise => { log.debug('Resolving import path based on directory structure'); - const contentDir = importConfig.contentDir || importConfig.data; + const contentDir = importConfig.contentDir; log.debug(`Content directory: ${contentDir}`); if (!fileExistsSync(contentDir)) { @@ -96,12 +96,6 @@ export const resolveImportPath = async (importConfig: ImportConfig, stackAPIClie return contentDir; } - const exportInfoPath = path.join(contentDir, 'export-info.json'); - if (fileExistsSync(exportInfoPath)) { - log.debug('Found export-info.json - using contentDir as-is (v2 export)'); - return contentDir; - } - const moduleTypes = defaultConfig.modules.types; const hasModuleFolders = moduleTypes.some((moduleType) => fileExistsSync(path.join(contentDir, moduleType))); @@ -139,31 +133,8 @@ export const updateImportConfigWithResolvedPath = async ( importConfig.contentDir = resolvedPath; - importConfig.data = resolvedPath; - - // Check if export-info.json exists to determine contentVersion - const exportInfoPath = path.join(resolvedPath, 'export-info.json'); - if (fileExistsSync(exportInfoPath)) { - try { - const exportInfo = await readFile(exportInfoPath); - // If export-info.json exists, set contentVersion to 2 (or use value from file if present) - if (exportInfo && exportInfo.contentVersion) { - importConfig.contentVersion = exportInfo.contentVersion; - } else { - // If export-info.json exists but contentVersion is missing, default to 2 - importConfig.contentVersion = 2; - } - } catch (error) { - // If export-info.json exists but is null or can't be read, default to 2 - importConfig.contentVersion = 2; - } - } else { - // If export-info.json doesn't exist, default to 1 (legacy format) - importConfig.contentVersion = 1; - } - log.debug( - `Import config updated - contentDir: ${importConfig.contentDir}, branchDir: ${importConfig.branchDir}, data: ${importConfig.data}, contentVersion: ${importConfig.contentVersion}`, + `Import config updated - contentDir: ${importConfig.contentDir}, branchDir: ${importConfig.branchDir}`, ); }; diff --git a/packages/contentstack-import/src/utils/logger.ts b/packages/contentstack-import/src/utils/logger.ts index f766334b3f..856beaeaba 100644 --- a/packages/contentstack-import/src/utils/logger.ts +++ b/packages/contentstack-import/src/utils/logger.ts @@ -140,7 +140,7 @@ function init(_logPath: string) { } export const log = async (config: ImportConfig, message: any, type: string) => { - config.cliLogsPath = sanitizePath(config.cliLogsPath || config.data || path.join(__dirname, 'logs')); + config.cliLogsPath = sanitizePath(config.cliLogsPath || config.contentDir || path.join(__dirname, 'logs')); // ignoring the type argument, as we are not using it to create a logfile anymore if (type !== 'error') { // removed type argument from init method diff --git a/packages/contentstack-import/src/utils/login-handler.ts b/packages/contentstack-import/src/utils/login-handler.ts index 859a4bf594..64f3612252 100644 --- a/packages/contentstack-import/src/utils/login-handler.ts +++ b/packages/contentstack-import/src/utils/login-handler.ts @@ -24,7 +24,7 @@ const login = async (config: ImportConfig): Promise => { log.debug('Login successful, setting up headers'); config.headers = { - api_key: config.source_stack, + api_key: config.apiKey, access_token: config.access_token, authtoken: config.authtoken, 'X-User-Agent': 'contentstack-export/v', @@ -40,7 +40,7 @@ const login = async (config: ImportConfig): Promise => { log.debug('Using existing authentication, validating stack access'); const stackAPIClient = client.stack({ - api_key: config.target_stack, + api_key: config.apiKey, management_token: config.management_token, }); diff --git a/packages/contentstack-import/src/utils/marketplace-app-helper.ts b/packages/contentstack-import/src/utils/marketplace-app-helper.ts index 4ed8e9f943..dd94d0e6d4 100644 --- a/packages/contentstack-import/src/utils/marketplace-app-helper.ts +++ b/packages/contentstack-import/src/utils/marketplace-app-helper.ts @@ -32,7 +32,7 @@ export const getAllStackSpecificApps = async ( const collection = await appSdk .marketplace(config.org_uid) .installation() - .fetchAll({ target_uids: config.target_stack, skip }) + .fetchAll({ target_uids: config.apiKey, skip }) .catch((error) => { handleAndLogError(error); log.error(error, config?.context); @@ -75,7 +75,7 @@ export const getOrgUid = async (config: ImportConfig): Promise => { const tempAPIClient = await managementSDKClient({ host: config.host }); const tempStackData = await tempAPIClient - .stack({ api_key: config.target_stack }) + .stack({ api_key: config.apiKey }) .fetch() .catch((error: any) => { handleAndLogError(error); diff --git a/packages/contentstack-import/test/unit/commands/cm/stacks/import.test.ts b/packages/contentstack-import/test/unit/commands/cm/stacks/import.test.ts index dba0747d86..94fec9421f 100644 --- a/packages/contentstack-import/test/unit/commands/cm/stacks/import.test.ts +++ b/packages/contentstack-import/test/unit/commands/cm/stacks/import.test.ts @@ -47,7 +47,6 @@ describe('ImportCommand', () => { apiKey: 'test', contentDir: '/test/data', data: '/test/data', - contentVersion: 1, region: 'us' as any, master_locale: { code: 'en-us' }, masterLocale: { code: 'en-us' }, diff --git a/packages/contentstack-import/test/unit/import/module-importer.test.ts b/packages/contentstack-import/test/unit/import/module-importer.test.ts index f715aa97e5..c0fafdd976 100644 --- a/packages/contentstack-import/test/unit/import/module-importer.test.ts +++ b/packages/contentstack-import/test/unit/import/module-importer.test.ts @@ -13,7 +13,6 @@ describe('ModuleImporter', () => { // Mock dependencies let startModuleImportStub: sinon.SinonStub; - let startJSModuleImportStub: sinon.SinonStub; let backupHandlerStub: sinon.SinonStub; let masterLocalDetailsStub: sinon.SinonStub; let sanitizeStackStub: sinon.SinonStub; @@ -45,7 +44,6 @@ describe('ModuleImporter', () => { mockImportConfig = { apiKey: 'test', management_token: undefined, - contentVersion: 1, backupDir: '/test/backup', data: '/test/data', cliLogsPath: '/test/logs', @@ -69,7 +67,6 @@ describe('ModuleImporter', () => { masterLocale: undefined, singleModuleImport: false, moduleName: undefined, - onlyTSModules: [], branchName: undefined, branchAlias: undefined, auditConfig: { @@ -102,8 +99,6 @@ describe('ModuleImporter', () => { const modulesIndex = require('../../../src/import/modules'); startModuleImportStub = sandbox.stub(modulesIndex, 'default').resolves(); - // startJSModuleImport is now the same as startModuleImport, so we stub the same module - startJSModuleImportStub = startModuleImportStub; // Mock @contentstack/cli-utilities // TODO: Fix addLocale mocking - currently skipping tests that need it @@ -356,7 +351,6 @@ describe('ModuleImporter', () => { expect(backupHandlerStub.calledOnce).to.be.true; expect(importer['importConfig'].backupDir).to.equal('/custom/backup/path'); - expect(importer['importConfig'].data).to.equal('/custom/backup/path'); }); it('should not modify config when backupHandler returns null', async () => { @@ -369,7 +363,6 @@ describe('ModuleImporter', () => { expect(backupHandlerStub.calledOnce).to.be.true; expect(importer['importConfig'].backupDir).to.equal(originalBackupDir); - expect(importer['importConfig'].data).to.equal(originalData); }); it('should continue execution when backupHandler fails', async () => { @@ -606,88 +599,6 @@ describe('ModuleImporter', () => { }); }); - describe('importByModuleByName()', () => { - describe('Content Version 2', () => { - it('should call startModuleImport when contentVersion === 2', async () => { - mockImportConfig.contentVersion = 2; - const importer = new ModuleImporter(mockManagementClient as any, mockImportConfig); - - await importer.importByModuleByName('entries'); - - expect(startModuleImportStub.calledOnce).to.be.true; - expect(startModuleImportStub.firstCall.args[0]).to.deep.equal({ - stackAPIClient: mockStackClient, - importConfig: mockImportConfig, - moduleName: 'entries' - }); - }); - - it('should pass correct moduleName to startModuleImport', async () => { - mockImportConfig.contentVersion = 2; - const importer = new ModuleImporter(mockManagementClient as any, mockImportConfig); - - await importer.importByModuleByName('assets'); - - expect(startModuleImportStub.firstCall.args[0].moduleName).to.equal('assets'); - }); - }); - - describe('Content Version 1', () => { - it('should call startModuleImport when contentVersion !== 2 and module is NOT in onlyTSModules', async () => { - mockImportConfig.contentVersion = 1; - mockImportConfig.onlyTSModules = ['personalize']; - const importer = new ModuleImporter(mockManagementClient as any, mockImportConfig); - - await importer.importByModuleByName('entries'); - - expect(startModuleImportStub.calledOnce).to.be.true; - expect(startModuleImportStub.firstCall.args[0]).to.deep.equal({ - stackAPIClient: mockStackClient, - importConfig: mockImportConfig, - moduleName: 'entries' - }); - }); - - it('should return undefined when contentVersion !== 2 and module IS in onlyTSModules', async () => { - mockImportConfig.contentVersion = 1; - mockImportConfig.onlyTSModules = ['entries', 'assets']; - const importer = new ModuleImporter(mockManagementClient as any, mockImportConfig); - - const result = await importer.importByModuleByName('entries'); - - expect(startModuleImportStub.called).to.be.false; - expect(result).to.be.undefined; - }); - - it('should handle multiple modules in onlyTSModules list', async () => { - mockImportConfig.contentVersion = 1; - mockImportConfig.onlyTSModules = ['entries', 'assets', 'content-types']; - const importer = new ModuleImporter(mockManagementClient as any, mockImportConfig); - - const result1 = await importer.importByModuleByName('entries'); - const result2 = await importer.importByModuleByName('assets'); - const result3 = await importer.importByModuleByName('content-types'); - const result4 = await importer.importByModuleByName('webhooks'); - - expect(result1).to.be.undefined; - expect(result2).to.be.undefined; - expect(result3).to.be.undefined; - expect(result4).to.be.undefined; // webhooks would call startJSModuleImport - expect(startModuleImportStub.calledOnce).to.be.true; - expect(startJSModuleImportStub.firstCall.args[0].moduleName).to.equal('webhooks'); - }); - - it('should handle empty onlyTSModules list', async () => { - mockImportConfig.contentVersion = 1; - mockImportConfig.onlyTSModules = []; - const importer = new ModuleImporter(mockManagementClient as any, mockImportConfig); - - await importer.importByModuleByName('entries'); - - expect(startModuleImportStub.calledOnce).to.be.true; - }); - }); - }); describe('importAllModules()', () => { it('should loop through all modules in modules.types', async () => { @@ -1160,12 +1071,6 @@ describe('ModuleImporter', () => { expect(importer['importConfig'].auditConfig.config.branch).to.be.undefined; }); - it('should handle empty onlyTSModules array', async () => { - mockImportConfig.onlyTSModules = []; - await moduleImporter.importByModuleByName('entries'); - - expect(startJSModuleImportStub.calledOnce).to.be.true; - }); it('should handle undefined auditConfig', async () => { mockImportConfig.auditConfig = undefined as any; diff --git a/packages/contentstack-import/test/unit/import/modules/assets.test.ts b/packages/contentstack-import/test/unit/import/modules/assets.test.ts index a7c069e4aa..e730857dd8 100644 --- a/packages/contentstack-import/test/unit/import/modules/assets.test.ts +++ b/packages/contentstack-import/test/unit/import/modules/assets.test.ts @@ -25,18 +25,17 @@ describe('ImportAssets', () => { asset: sinon.stub().returns({ create: sinon.stub().resolves({ uid: 'asset-123', url: 'https://example.com/asset.jpg' }), folder: sinon.stub().returns({ - create: sinon.stub().resolves({ uid: 'folder-123' }) + create: sinon.stub().resolves({ uid: 'folder-123' }), }), replace: sinon.stub().resolves({ uid: 'asset-123', url: 'https://example.com/asset.jpg' }), - publish: sinon.stub().resolves({ uid: 'asset-123' }) - }) + publish: sinon.stub().resolves({ uid: 'asset-123' }), + }), }; mockImportConfig = { apiKey: 'test', contentDir: '/test/content', data: '/test/content', - contentVersion: 1, region: 'us', master_locale: { code: 'en-us' }, masterLocale: { code: 'en-us' }, @@ -48,11 +47,11 @@ describe('ImportAssets', () => { sessionId: 'session-123', apiKey: 'test', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, modules: { types: ['assets'], - assets: { + assets: { dirName: 'assets', validKeys: ['title', 'filename', 'content_type', 'parent_uid', 'description', 'tags'], folderValidKeys: ['name', 'parent_uid'], @@ -61,8 +60,8 @@ describe('ImportAssets', () => { uploadAssetsConcurrency: 5, includeVersionedAssets: true, importSameStructure: false, - displayExecutionTime: false - } + displayExecutionTime: false, + }, }, backupDir: '/test/backup', cliLogsPath: '/test/logs', @@ -75,13 +74,13 @@ describe('ImportAssets', () => { skipAudit: false, skipAssetsPublish: false, 'exclude-global-modules': false, - replaceExisting: false + replaceExisting: false, } as any; importAssets = new ImportAssets({ importConfig: mockImportConfig as any, stackAPIClient: mockStackClient, - moduleName: 'assets' + moduleName: 'assets', }); }); @@ -90,20 +89,20 @@ describe('ImportAssets', () => { }); describe('Constructor', () => { - it('should initialize with correct parameters', () => { - expect(importAssets).to.be.instanceOf(ImportAssets); - expect(importAssets['importConfig']).to.equal(mockImportConfig); - expect((importAssets as any)['client']).to.equal(mockStackClient); - }); + it('should initialize with correct parameters', () => { + expect(importAssets).to.be.instanceOf(ImportAssets); + expect(importAssets['importConfig']).to.equal(mockImportConfig); + expect((importAssets as any)['client']).to.equal(mockStackClient); + }); - it('should have assetConfig property', () => { - expect(importAssets.assetConfig).to.be.an('object'); - expect(importAssets.assetConfig).to.have.property('dirName', 'assets'); - }); + it('should have assetConfig property', () => { + expect(importAssets.assetConfig).to.be.an('object'); + expect(importAssets.assetConfig).to.have.property('dirName', 'assets'); + }); - it('should set context module to assets', () => { - expect(importAssets['importConfig'].context.module).to.equal('assets'); - }); + it('should set context module to assets', () => { + expect(importAssets['importConfig'].context.module).to.equal('assets'); + }); it('should initialize paths correctly', () => { expect(importAssets['assetsPath']).to.include('assets'); @@ -140,25 +139,29 @@ describe('ImportAssets', () => { publishStub = sinon.stub(importAssets as any, 'publish').resolves(); existsSyncStub = sinon.stub().returns(true); sinon.replace(require('node:fs'), 'existsSync', existsSyncStub); - + analyzeImportDataStub = sinon.stub(importAssets as any, 'analyzeImportData').resolves([1, 2, 0, 1]); - withLoadingSpinnerStub = sinon.stub(importAssets as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + withLoadingSpinnerStub = sinon + .stub(importAssets as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); createNestedProgressStub = sinon.stub(importAssets as any, 'createNestedProgress').returns({ addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }); sinon.stub(importAssets as any, 'initializeProgress').resolves(); sinon.stub(importAssets as any, 'completeProgress').resolves(); - executeStepStub = sinon.stub(importAssets as any, 'executeStep').callsFake(async (progress: any, processName: string, status: string, fn: () => Promise) => { - // Call the function to ensure the actual methods are invoked - if (fn) { - return await fn(); - } - }); + executeStepStub = sinon + .stub(importAssets as any, 'executeStep') + .callsFake(async (progress: any, processName: string, status: string, fn: () => Promise) => { + // Call the function to ensure the actual methods are invoked + if (fn) { + return await fn(); + } + }); }); it('should call importFolders first', async () => { @@ -262,7 +265,7 @@ describe('ImportAssets', () => { it('should import folders successfully', async () => { const mockFolders = [ { uid: 'folder-1', name: 'Folder 1', parent_uid: null, created_at: '2023-01-01' }, - { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' } + { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' }, ]; fsUtilityReadFileStub.returns(mockFolders); @@ -274,7 +277,7 @@ describe('ImportAssets', () => { it('should construct folder import order', async () => { const mockFolders = [ { uid: 'folder-1', name: 'Folder 1', parent_uid: null, created_at: '2023-01-01' }, - { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' } + { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' }, ]; fsUtilityReadFileStub.returns(mockFolders); const constructStub = sinon.stub(importAssets as any, 'constructFolderImportOrder').returns(mockFolders); @@ -286,17 +289,15 @@ describe('ImportAssets', () => { }); it('should write folder mappings after import', async () => { - const mockFolders = [ - { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' } - ]; + const mockFolders = [{ uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' }]; fsUtilityReadFileStub.returns(mockFolders); - + // Simulate successful folder creation makeConcurrentCallStub.callsFake(async (options) => { const onSuccess = options.apiParams.resolve; onSuccess({ response: { uid: 'new-folder-1' }, - apiData: { uid: 'folder-1', name: 'Folder 1' } + apiData: { uid: 'folder-1', name: 'Folder 1' }, }); }); @@ -306,16 +307,14 @@ describe('ImportAssets', () => { }); it('should handle onSuccess callback correctly', async () => { - const mockFolders = [ - { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' } - ]; + const mockFolders = [{ uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' }]; fsUtilityReadFileStub.returns(mockFolders); makeConcurrentCallStub.callsFake(async (options) => { const onSuccess = options.apiParams.resolve; onSuccess({ response: { uid: 'new-folder-1' }, - apiData: { uid: 'folder-1', name: 'Folder 1' } + apiData: { uid: 'folder-1', name: 'Folder 1' }, }); }); @@ -325,16 +324,14 @@ describe('ImportAssets', () => { }); it('should handle onReject callback correctly', async () => { - const mockFolders = [ - { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' } - ]; + const mockFolders = [{ uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' }]; fsUtilityReadFileStub.returns(mockFolders); makeConcurrentCallStub.callsFake(async (options) => { const onReject = options.apiParams.reject; onReject({ error: new Error('Failed to create folder'), - apiData: { name: 'Folder 1' } + apiData: { name: 'Folder 1' }, }); }); @@ -346,7 +343,7 @@ describe('ImportAssets', () => { it('should map parent folder UIDs in serializeData', async () => { const mockFolders = [ { uid: 'folder-1', name: 'Folder 1', parent_uid: null, created_at: '2023-01-01' }, - { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' } + { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' }, ]; fsUtilityReadFileStub.returns(mockFolders); importAssets['assetsFolderMap'] = { 'folder-1': 'new-folder-1' }; @@ -355,7 +352,7 @@ describe('ImportAssets', () => { makeConcurrentCallStub.callsFake(async (options) => { const serializeData = options.apiParams.serializeData; capturedApiOptions = serializeData({ - apiData: { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1' } + apiData: { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1' }, }); }); @@ -371,19 +368,19 @@ describe('ImportAssets', () => { beforeEach(() => { makeConcurrentCallStub = sinon.stub(importAssets as any, 'makeConcurrentCall').resolves(); - + fsUtilityStub = sinon.stub(FsUtility.prototype, 'constructor' as any); Object.defineProperty(FsUtility.prototype, 'indexFileContent', { get: sinon.stub().returns({ '0': 'chunk-0' }), - configurable: true + configurable: true, }); Object.defineProperty(FsUtility.prototype, 'readChunkFiles', { get: sinon.stub().returns({ next: sinon.stub().resolves({ - 'asset-1': { uid: 'asset-1', title: 'Asset 1', url: 'url-1', filename: 'file1.jpg', _version: 1 } - }) + 'asset-1': { uid: 'asset-1', title: 'Asset 1', url: 'url-1', filename: 'file1.jpg', _version: 1 }, + }), }), - configurable: true + configurable: true, }); }); @@ -412,10 +409,10 @@ describe('ImportAssets', () => { get: sinon.stub().returns({ next: sinon.stub().resolves({ 'asset-1': { uid: 'asset-1', title: 'Asset 1', _version: 1 }, - 'asset-2': { uid: 'asset-2', title: 'Asset 2', _version: 2 } - }) + 'asset-2': { uid: 'asset-2', title: 'Asset 2', _version: 2 }, + }), }), - configurable: true + configurable: true, }); await (importAssets as any).importAssets(true); @@ -454,7 +451,7 @@ describe('ImportAssets', () => { const onSuccess = options.apiParams.resolve; onSuccess({ response: { uid: 'new-asset-1', url: 'new-url-1' }, - apiData: { uid: 'asset-1', url: 'url-1', title: 'Asset 1' } + apiData: { uid: 'asset-1', url: 'url-1', title: 'Asset 1' }, }); }); @@ -469,7 +466,7 @@ describe('ImportAssets', () => { const onReject = options.apiParams.reject; onReject({ error: new Error('Upload failed'), - apiData: { title: 'Asset 1' } + apiData: { title: 'Asset 1' }, }); }); @@ -481,9 +478,9 @@ describe('ImportAssets', () => { it('should handle chunk read errors', async () => { Object.defineProperty(FsUtility.prototype, 'readChunkFiles', { get: sinon.stub().returns({ - next: sinon.stub().rejects(new Error('Read failed')) + next: sinon.stub().rejects(new Error('Read failed')), }), - configurable: true + configurable: true, }); await (importAssets as any).importAssets(false); @@ -498,7 +495,7 @@ describe('ImportAssets', () => { const testImportAssets = new ImportAssets({ importConfig: mockImportConfig as any, stackAPIClient: mockStackClient, - moduleName: 'assets' + moduleName: 'assets', }); testImportAssets['assetConfig'].importSameStructure = false; testImportAssets['assetConfig'].includeVersionedAssets = false; @@ -506,7 +503,7 @@ describe('ImportAssets', () => { const apiOptions = { entity: 'create-assets' as const, - apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' } + apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' }, }; const result = (testImportAssets as any).serializeAssets(apiOptions); @@ -517,7 +514,7 @@ describe('ImportAssets', () => { it('should set upload path for asset', () => { const apiOptions = { entity: 'create-assets' as const, - apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' } + apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' }, }; const result = (importAssets as any).serializeAssets(apiOptions); @@ -531,7 +528,7 @@ describe('ImportAssets', () => { const apiOptions = { entity: 'create-assets' as const, - apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg', parent_uid: 'folder-1' } + apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg', parent_uid: 'folder-1' }, }; const result = (importAssets as any).serializeAssets(apiOptions); @@ -546,7 +543,7 @@ describe('ImportAssets', () => { const apiOptions = { entity: 'create-assets' as const, - apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' } + apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' }, }; const result = (importAssets as any).serializeAssets(apiOptions); @@ -562,7 +559,7 @@ describe('ImportAssets', () => { const apiOptions = { entity: 'create-assets' as const, - apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' } + apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' }, }; const result = (importAssets as any).serializeAssets(apiOptions); @@ -579,7 +576,7 @@ describe('ImportAssets', () => { const apiOptions = { entity: 'create-assets' as const, - apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' } + apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' }, }; const result = (importAssets as any).serializeAssets(apiOptions); @@ -596,10 +593,10 @@ describe('ImportAssets', () => { makeConcurrentCallStub = sinon.stub(importAssets as any, 'makeConcurrentCall').resolves(); importAssets['assetsUidMap'] = { 'asset-1': 'new-asset-1' }; importAssets['environments'] = { 'env-1': { name: 'production' } }; - + Object.defineProperty(FsUtility.prototype, 'indexFileContent', { get: sinon.stub().returns({ '0': 'chunk-0' }), - configurable: true + configurable: true, }); Object.defineProperty(FsUtility.prototype, 'readChunkFiles', { get: sinon.stub().returns({ @@ -607,13 +604,11 @@ describe('ImportAssets', () => { { uid: 'asset-1', title: 'Asset 1', - publish_details: [ - { environment: 'env-1', locale: 'en-us' } - ] - } - ]) + publish_details: [{ environment: 'env-1', locale: 'en-us' }], + }, + ]), }), - configurable: true + configurable: true, }); }); @@ -634,11 +629,9 @@ describe('ImportAssets', () => { it('should skip assets without publish_details', async () => { Object.defineProperty(FsUtility.prototype, 'readChunkFiles', { get: sinon.stub().returns({ - next: sinon.stub().resolves([ - { uid: 'asset-1', title: 'Asset 1', publish_details: [] } - ]) + next: sinon.stub().resolves([{ uid: 'asset-1', title: 'Asset 1', publish_details: [] }]), }), - configurable: true + configurable: true, }); await (importAssets as any).publish(); @@ -656,7 +649,7 @@ describe('ImportAssets', () => { makeConcurrentCallStub.callsFake(async (options) => { const onSuccess = options.apiParams.resolve; onSuccess({ - apiData: { uid: 'asset-1', title: 'Asset 1' } + apiData: { uid: 'asset-1', title: 'Asset 1' }, }); }); @@ -670,7 +663,7 @@ describe('ImportAssets', () => { const onReject = options.apiParams.reject; onReject({ error: new Error('Publish failed'), - apiData: { uid: 'asset-1', title: 'Asset 1' } + apiData: { uid: 'asset-1', title: 'Asset 1' }, }); }); @@ -689,11 +682,11 @@ describe('ImportAssets', () => { uid: 'asset-1', publish_details: [ { environment: 'env-1', locale: 'en-us' }, - { environment: 'env-invalid', locale: 'en-us' } - ] - } + { environment: 'env-invalid', locale: 'en-us' }, + ], + }, }); - + expect(result.apiData.environments).to.deep.equal(['production']); expect(result.apiData.locales).to.deep.equal(['en-us']); }); @@ -707,12 +700,10 @@ describe('ImportAssets', () => { const result = serializeData({ apiData: { uid: 'asset-1', - publish_details: [ - { environment: 'env-invalid', locale: 'en-us' } - ] - } + publish_details: [{ environment: 'env-invalid', locale: 'en-us' }], + }, }); - + expect(result.entity).to.be.undefined; }); @@ -727,10 +718,10 @@ describe('ImportAssets', () => { const result = serializeData({ apiData: { uid: 'asset-unknown', - publish_details: [{ environment: 'env-1', locale: 'en-us' }] - } + publish_details: [{ environment: 'env-1', locale: 'en-us' }], + }, }); - + expect(result.entity).to.be.undefined; }); @@ -745,10 +736,10 @@ describe('ImportAssets', () => { const result = serializeData({ apiData: { uid: 'asset-1', - publish_details: [{ environment: 'env-1', locale: 'en-us' }] - } + publish_details: [{ environment: 'env-1', locale: 'en-us' }], + }, }); - + expect(result.uid).to.equal('mapped-asset-1'); }); @@ -764,11 +755,11 @@ describe('ImportAssets', () => { publish_details: [ { environment: 'env-1', locale: 'en-us' }, { environment: 'env-1', locale: 'en-us' }, - { environment: 'env-1', locale: 'fr-fr' } - ] - } + { environment: 'env-1', locale: 'fr-fr' }, + ], + }, }); - + expect(result.apiData.locales).to.have.lengthOf(2); expect(result.apiData.locales).to.include.members(['en-us', 'fr-fr']); }); @@ -781,7 +772,7 @@ describe('ImportAssets', () => { it('should order folders with null parent_uid first', () => { const folders = [ { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' }, - { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' } + { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' }, ]; const result = (importAssets as any).constructFolderImportOrder(folders); @@ -794,7 +785,7 @@ describe('ImportAssets', () => { const folders = [ { uid: 'folder-3', name: 'Folder 3', parent_uid: 'folder-2', created_at: '2023-01-03' }, { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' }, - { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' } + { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' }, ]; const result = (importAssets as any).constructFolderImportOrder(folders); @@ -807,7 +798,7 @@ describe('ImportAssets', () => { it('should handle multiple root folders', () => { const folders = [ { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' }, - { uid: 'folder-2', name: 'Folder 2', parent_uid: null as any, created_at: '2023-01-02' } + { uid: 'folder-2', name: 'Folder 2', parent_uid: null as any, created_at: '2023-01-02' }, ]; const result = (importAssets as any).constructFolderImportOrder(folders); @@ -822,7 +813,7 @@ describe('ImportAssets', () => { { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' }, { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' }, { uid: 'folder-3', name: 'Folder 3', parent_uid: 'folder-2', created_at: '2023-01-03' }, - { uid: 'folder-4', name: 'Folder 4', parent_uid: 'folder-3', created_at: '2023-01-04' } + { uid: 'folder-4', name: 'Folder 4', parent_uid: 'folder-3', created_at: '2023-01-04' }, ]; const result = (importAssets as any).constructFolderImportOrder(folders); @@ -833,9 +824,7 @@ describe('ImportAssets', () => { it('should add root folder when replaceExisting is true', () => { mockImportConfig.replaceExisting = true; - const folders = [ - { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' } - ]; + const folders = [{ uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' }]; const result = (importAssets as any).constructFolderImportOrder(folders); @@ -846,9 +835,7 @@ describe('ImportAssets', () => { it('should update root folder parent_uid when replaceExisting', () => { mockImportConfig.replaceExisting = true; - const folders = [ - { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' } - ]; + const folders = [{ uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' }]; const result = (importAssets as any).constructFolderImportOrder(folders); @@ -860,7 +847,7 @@ describe('ImportAssets', () => { mockImportConfig.replaceExisting = true; const folders = [ { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' }, - { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' } + { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' }, ]; const result = (importAssets as any).constructFolderImportOrder(folders); @@ -882,7 +869,7 @@ describe('ImportAssets', () => { it('should maintain created_at timestamps', () => { const folders = [ { uid: 'folder-1', name: 'Folder 1', parent_uid: null as any, created_at: '2023-01-01' }, - { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' } + { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' }, ]; const result = (importAssets as any).constructFolderImportOrder(folders); @@ -905,13 +892,15 @@ describe('ImportAssets', () => { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }); sinon.stub(importAssets as any, 'initializeProgress').resolves(); sinon.stub(importAssets as any, 'completeProgress').resolves(); - sinon.stub(importAssets as any, 'executeStep').callsFake(async (progress: any, processName: string, status: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importAssets as any, 'executeStep') + .callsFake(async (progress: any, processName: string, status: string, fn: () => Promise) => { + return await fn(); + }); await importAssets.start(); @@ -936,15 +925,17 @@ describe('ImportAssets', () => { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }); sinon.stub(importAssets as any, 'initializeProgress').resolves(); sinon.stub(importAssets as any, 'completeProgress').resolves(); - sinon.stub(importAssets as any, 'executeStep').callsFake(async (progress: any, processName: string, status: string, fn: () => Promise) => { - if (fn) { - return await fn(); - } - }); + sinon + .stub(importAssets as any, 'executeStep') + .callsFake(async (progress: any, processName: string, status: string, fn: () => Promise) => { + if (fn) { + return await fn(); + } + }); const testImportFoldersStub = sinon.stub(importAssets as any, 'importFolders').resolves(); const testImportAssetsStub = sinon.stub(importAssets as any, 'importAssets').resolves(); @@ -970,15 +961,17 @@ describe('ImportAssets', () => { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }); sinon.stub(importAssets as any, 'initializeProgress').resolves(); sinon.stub(importAssets as any, 'completeProgress').resolves(); - sinon.stub(importAssets as any, 'executeStep').callsFake(async (progress: any, processName: string, status: string, fn: () => Promise) => { - if (fn) { - return await fn(); - } - }); + sinon + .stub(importAssets as any, 'executeStep') + .callsFake(async (progress: any, processName: string, status: string, fn: () => Promise) => { + if (fn) { + return await fn(); + } + }); const importFoldersStub = sinon.stub(importAssets as any, 'importFolders').resolves(); const importAssetsStub = sinon.stub(importAssets as any, 'importAssets').resolves(); @@ -1005,10 +998,10 @@ describe('ImportAssets', () => { it('should handle empty environments object', () => { importAssets['environments'] = {}; - + const apiOptions = { entity: 'create-assets' as const, - apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' } + apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' }, }; const result = (importAssets as any).serializeAssets(apiOptions); @@ -1018,7 +1011,7 @@ describe('ImportAssets', () => { it('should handle assets without parent_uid', () => { const apiOptions = { entity: 'create-assets' as const, - apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' } + apiData: { uid: 'asset-1', title: 'Asset 1', filename: 'file1.jpg' }, }; const result = (importAssets as any).serializeAssets(apiOptions); @@ -1027,9 +1020,7 @@ describe('ImportAssets', () => { }); it('should handle malformed folder structure', () => { - const folders = [ - { uid: 'folder-1', name: 'Folder 1', parent_uid: 'non-existent', created_at: '2023-01-01' } - ]; + const folders = [{ uid: 'folder-1', name: 'Folder 1', parent_uid: 'non-existent', created_at: '2023-01-01' }]; const result = (importAssets as any).constructFolderImportOrder(folders); @@ -1040,7 +1031,7 @@ describe('ImportAssets', () => { it('should handle circular folder references', () => { const folders = [ { uid: 'folder-1', name: 'Folder 1', parent_uid: 'folder-2', created_at: '2023-01-01' }, - { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' } + { uid: 'folder-2', name: 'Folder 2', parent_uid: 'folder-1', created_at: '2023-01-02' }, ]; const result = (importAssets as any).constructFolderImportOrder(folders); @@ -1052,21 +1043,21 @@ describe('ImportAssets', () => { it('should handle assets with empty publish_details array', async () => { Object.defineProperty(FsUtility.prototype, 'indexFileContent', { get: sinon.stub().returns({ '0': 'chunk-0' }), - configurable: true + configurable: true, }); Object.defineProperty(FsUtility.prototype, 'readChunkFiles', { get: sinon.stub().returns({ - next: sinon.stub().resolves([ - { uid: 'asset-1', title: 'Asset 1', publish_details: [] } - ]) + next: sinon.stub().resolves([{ uid: 'asset-1', title: 'Asset 1', publish_details: [] }]), }), - configurable: true + configurable: true, }); - const makeConcurrentStub = sinon.stub(importAssets as any, 'makeConcurrentCall').callsFake(async (options: any) => { - // When publish_details is empty, the asset should be filtered out - expect(options.apiContent).to.have.lengthOf(0); - }); + const makeConcurrentStub = sinon + .stub(importAssets as any, 'makeConcurrentCall') + .callsFake(async (options: any) => { + // When publish_details is empty, the asset should be filtered out + expect(options.apiContent).to.have.lengthOf(0); + }); await (importAssets as any).publish(); expect(makeConcurrentStub.called).to.be.true; @@ -1074,7 +1065,7 @@ describe('ImportAssets', () => { it('should handle special characters in folder names', () => { const folders = [ - { uid: 'folder-1', name: 'Folder & Special "Chars"', parent_uid: null as any, created_at: '2023-01-01' } + { uid: 'folder-1', name: 'Folder & Special "Chars"', parent_uid: null as any, created_at: '2023-01-01' }, ]; const result = (importAssets as any).constructFolderImportOrder(folders); @@ -1089,7 +1080,7 @@ describe('ImportAssets', () => { uid: `folder-${i}`, name: `Folder ${i}`, parent_uid: i === 0 ? null : `folder-${i - 1}`, - created_at: `2023-01-${String(i + 1).padStart(2, '0')}` + created_at: `2023-01-${String(i + 1).padStart(2, '0')}`, }); } diff --git a/packages/contentstack-import/test/unit/import/modules/base-class.test.ts b/packages/contentstack-import/test/unit/import/modules/base-class.test.ts index d156c4b225..290cf4bc8e 100644 --- a/packages/contentstack-import/test/unit/import/modules/base-class.test.ts +++ b/packages/contentstack-import/test/unit/import/modules/base-class.test.ts @@ -23,72 +23,71 @@ describe('BaseClass', () => { replace: sinon.stub().resolves({ uid: 'asset-123' }), publish: sinon.stub().resolves({ uid: 'asset-123' }), folder: sinon.stub().returns({ - create: sinon.stub().resolves({ uid: 'folder-123' }) - }) + create: sinon.stub().resolves({ uid: 'folder-123' }), + }), }), contentType: sinon.stub().returns({ create: sinon.stub().resolves({ uid: 'ct-123' }), entry: sinon.stub().returns({ create: sinon.stub().resolves({ uid: 'entry-123' }), publish: sinon.stub().resolves({ uid: 'entry-123' }), - delete: sinon.stub().resolves({ uid: 'entry-123' }) - }) + delete: sinon.stub().resolves({ uid: 'entry-123' }), + }), }), locale: sinon.stub().returns({ create: sinon.stub().resolves({ uid: 'locale-123' }), fetch: sinon.stub().resolves({ name: 'French', fallback_locale: 'en-us', - update: sinon.stub().resolves({ code: 'fr-fr' }) - }) + update: sinon.stub().resolves({ code: 'fr-fr' }), + }), }), extension: sinon.stub().returns({ create: sinon.stub().resolves({ uid: 'ext-123' }), fetch: sinon.stub().resolves({ scope: 'local', - update: sinon.stub().resolves({ uid: 'ext-123' }) - }) + update: sinon.stub().resolves({ uid: 'ext-123' }), + }), }), environment: sinon.stub().returns({ - create: sinon.stub().resolves({ uid: 'env-123' }) + create: sinon.stub().resolves({ uid: 'env-123' }), }), label: sinon.stub().returns({ create: sinon.stub().resolves({ uid: 'label-123' }), fetch: sinon.stub().resolves({ parent: 'old-parent', - update: sinon.stub().resolves({ uid: 'label-123' }) - }) + update: sinon.stub().resolves({ uid: 'label-123' }), + }), }), webhook: sinon.stub().returns({ - create: sinon.stub().resolves({ uid: 'webhook-123' }) + create: sinon.stub().resolves({ uid: 'webhook-123' }), }), workflow: sinon.stub().returns({ - create: sinon.stub().resolves({ uid: 'workflow-123' }) + create: sinon.stub().resolves({ uid: 'workflow-123' }), }), role: sinon.stub().returns({ - create: sinon.stub().resolves({ uid: 'role-123' }) + create: sinon.stub().resolves({ uid: 'role-123' }), }), taxonomy: sinon.stub().returns({ create: sinon.stub().resolves({ uid: 'taxonomy-123' }), terms: sinon.stub().returns({ - create: sinon.stub().resolves({ uid: 'term-123' }) + create: sinon.stub().resolves({ uid: 'term-123' }), }), - import: sinon.stub().resolves({ uid: 'import-123' }) + import: sinon.stub().resolves({ uid: 'import-123' }), }), globalField: sinon.stub().returns({ create: sinon.stub().resolves({ uid: 'gf-123' }), fetch: sinon.stub().resolves({ title: 'Test GF', - update: sinon.stub().resolves({ uid: 'gf-123' }) - }) - }) + update: sinon.stub().resolves({ uid: 'gf-123' }), + }), + }), }; mockImportConfig = { apiKey: 'test', contentDir: '/test/content', data: '/test/content', - contentVersion: 1, region: { name: 'us', cma: 'https://api.contentstack.io' } as any, master_locale: { code: 'en-us' }, masterLocale: { code: 'en-us' }, @@ -100,7 +99,7 @@ describe('BaseClass', () => { sessionId: 'session-123', apiKey: 'test', orgId: 'org-123', - authenticationMethod: 'Management Token' + authenticationMethod: 'Management Token', }, modules: { types: ['assets', 'content-types'], @@ -114,15 +113,15 @@ describe('BaseClass', () => { importFoldersConcurrency: 1, displayExecutionTime: false, includeVersionedAssets: false, - importSameStructure: false + importSameStructure: false, }, contentTypes: { writeConcurrency: 1, dirName: 'content_types', fileName: 'content_types.json', validKeys: ['title', 'uid', 'schema'], - apiConcurrency: 1 - } + apiConcurrency: 1, + }, } as any, backupDir: '/test/backup', cliLogsPath: '/test/logs', @@ -133,12 +132,12 @@ describe('BaseClass', () => { auth_token: 'auth-token', selectedModules: ['assets'], skipAudit: false, - 'exclude-global-modules': false + 'exclude-global-modules': false, } as any; testClass = new TestBaseClass({ importConfig: mockImportConfig, - stackAPIClient: mockStackClient + stackAPIClient: mockStackClient, }); }); @@ -178,7 +177,7 @@ describe('BaseClass', () => { const start = Date.now(); await testClass.delay(100); const end = Date.now(); - + expect(end - start).to.be.at.least(90); // Allow some tolerance }); @@ -186,7 +185,7 @@ describe('BaseClass', () => { const start = Date.now(); await testClass.delay(0); const end = Date.now(); - + expect(end - start).to.be.at.most(10); // Should be very fast }); @@ -194,7 +193,7 @@ describe('BaseClass', () => { const start = Date.now(); await testClass.delay(-100); const end = Date.now(); - + expect(end - start).to.be.at.most(10); // Should be very fast }); @@ -213,13 +212,13 @@ describe('BaseClass', () => { mockApiContent = [ { uid: 'item1', title: 'Item 1' }, { uid: 'item2', title: 'Item 2' }, - { uid: 'item3', title: 'Item 3' } + { uid: 'item3', title: 'Item 3' }, ] as any[]; mockApiParams = { entity: 'create-assets', uid: 'test-uid', resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; mockProcessName = 'test-process'; }); @@ -231,7 +230,7 @@ describe('BaseClass', () => { processName: mockProcessName, indexerCount: 1, currentIndexer: 1, - concurrencyLimit: 2 + concurrencyLimit: 2, }; await testClass.makeConcurrentCall(env); @@ -246,7 +245,7 @@ describe('BaseClass', () => { processName: mockProcessName, indexerCount: 1, currentIndexer: 1, - concurrencyLimit: 2 + concurrencyLimit: 2, }; await testClass.makeConcurrentCall(env, customHandler); @@ -264,7 +263,7 @@ describe('BaseClass', () => { processName: mockProcessName, indexerCount: 1, currentIndexer: 1, - concurrencyLimit: 2 + concurrencyLimit: 2, }; await testClass.makeConcurrentCall(env); @@ -279,7 +278,7 @@ describe('BaseClass', () => { processName: mockProcessName, indexerCount: 1, currentIndexer: 1, - concurrencyLimit: 2 + concurrencyLimit: 2, }; await testClass.makeConcurrentCall(env); @@ -294,7 +293,7 @@ describe('BaseClass', () => { processName: mockProcessName, indexerCount: 1, currentIndexer: 1, - concurrencyLimit: 2 + concurrencyLimit: 2, }; await testClass.makeConcurrentCall(env); @@ -308,7 +307,7 @@ describe('BaseClass', () => { apiParams: mockApiParams, processName: mockProcessName, indexerCount: 1, - currentIndexer: 1 + currentIndexer: 1, // No concurrencyLimit specified }; @@ -329,15 +328,7 @@ describe('BaseClass', () => { }); it('should log batch completion message when enabled', async () => { - await testClass.logMsgAndWaitIfRequired( - 'test-process', - Date.now() - 500, - 5, - 2, - true, - 10, - 3 - ); + await testClass.logMsgAndWaitIfRequired('test-process', Date.now() - 500, 5, 2, true, 10, 3); // The log.debug is called in the real method, so we can't easily test the stub // This test verifies that the method executes without throwing errors @@ -345,27 +336,13 @@ describe('BaseClass', () => { }); it('should not log when logBatchCompletionMsg is false', async () => { - await testClass.logMsgAndWaitIfRequired( - 'test-process', - Date.now() - 500, - 5, - 2, - false - ); + await testClass.logMsgAndWaitIfRequired('test-process', Date.now() - 500, 5, 2, false); expect(logDebugStub.called).to.be.false; }); it('should include current chunk processing info when provided', async () => { - await testClass.logMsgAndWaitIfRequired( - 'test-process', - Date.now() - 500, - 5, - 2, - true, - 10, - 3 - ); + await testClass.logMsgAndWaitIfRequired('test-process', Date.now() - 500, 5, 2, true, 10, 3); expect(true).to.be.true; }); @@ -377,7 +354,7 @@ describe('BaseClass', () => { start - 100, // 100ms execution time 5, 2, - true + true, ); const end = Date.now(); @@ -391,23 +368,17 @@ describe('BaseClass', () => { start - 1500, // 1500ms execution time 5, 2, - true + true, ); const end = Date.now(); - expect(end - start).to.be.at.most(100); + expect(end - start).to.be.at.most(100); }); it('should display execution time when enabled', async () => { mockImportConfig.modules.assets.displayExecutionTime = true; - - await testClass.logMsgAndWaitIfRequired( - 'test-process', - Date.now() - 500, - 5, - 2, - true - ); + + await testClass.logMsgAndWaitIfRequired('test-process', Date.now() - 500, 5, 2, true); expect(consoleLogStub.calledOnce).to.be.true; expect(consoleLogStub.firstCall.args[0]).to.include('Time taken to execute'); @@ -425,7 +396,7 @@ describe('BaseClass', () => { reject: sinon.stub(), apiData: { title: 'Test Asset', filename: 'test.jpg' }, additionalInfo: {}, - includeParamOnCompletion: false + includeParamOnCompletion: false, }; }); @@ -529,7 +500,7 @@ describe('BaseClass', () => { reject: sinon.stub(), apiData: { title: 'Test Asset', filename: 'test.jpg' }, additionalInfo: {}, - includeParamOnCompletion: false + includeParamOnCompletion: false, }; }); @@ -579,10 +550,10 @@ describe('BaseClass', () => { it('should handle update-extensions', async () => { mockApiOptions.entity = 'update-extensions' as any; mockApiOptions.apiData = { uid: 'ext-123', scope: 'global' }; - + const mockExtension = { scope: 'local', - update: sinon.stub().resolves({ uid: 'ext-123' }) + update: sinon.stub().resolves({ uid: 'ext-123' }), }; mockStackClient.extension().fetch.resolves(mockExtension); @@ -608,11 +579,11 @@ describe('BaseClass', () => { it('should handle update-locale', async () => { mockApiOptions.entity = 'update-locale' as any; mockApiOptions.apiData = { code: 'fr-fr', name: 'French Updated', fallback_locale: 'en-us' }; - + const mockLocale = { name: 'French', fallback_locale: 'en-us', - update: sinon.stub().resolves({ code: 'fr-fr' }) + update: sinon.stub().resolves({ code: 'fr-fr' }), }; mockStackClient.locale().fetch.resolves(mockLocale); @@ -661,10 +632,10 @@ describe('BaseClass', () => { it('should handle update-gfs with uid in apiData', async () => { mockApiOptions.entity = 'update-gfs' as any; mockApiOptions.apiData = { uid: 'gf-123', title: 'Updated GF' }; - + const mockGF = { title: 'Test GF', - update: sinon.stub().resolves({ uid: 'gf-123' }) + update: sinon.stub().resolves({ uid: 'gf-123' }), }; mockStackClient.globalField().fetch.resolves(mockGF); @@ -678,10 +649,10 @@ describe('BaseClass', () => { it('should handle update-gfs with uid in global_field', async () => { mockApiOptions.entity = 'update-gfs' as any; mockApiOptions.apiData = { global_field: { uid: 'gf-123' }, title: 'Updated GF' }; - + const mockGF = { title: 'Test GF', - update: sinon.stub().resolves({ uid: 'gf-123' }) + update: sinon.stub().resolves({ uid: 'gf-123' }), }; mockStackClient.globalField().fetch.resolves(mockGF); @@ -719,10 +690,10 @@ describe('BaseClass', () => { it('should handle update-labels', async () => { mockApiOptions.entity = 'update-labels' as any; mockApiOptions.apiData = { uid: 'label-123', parent: 'parent-123' }; - + const mockLabel = { parent: 'old-parent', - update: sinon.stub().resolves({ uid: 'label-123' }) + update: sinon.stub().resolves({ uid: 'label-123' }), }; mockStackClient.label().fetch.resolves(mockLabel); @@ -775,10 +746,10 @@ describe('BaseClass', () => { mockApiOptions.entity = 'create-entries' as any; const mockEntry = { uid: 'entry-123', update: sinon.stub().resolves({ uid: 'entry-123' }) }; mockApiOptions.apiData = mockEntry; - mockApiOptions.additionalInfo = { - cTUid: 'ct-123', + mockApiOptions.additionalInfo = { + cTUid: 'ct-123', locale: 'en-us', - [mockEntry.uid]: { isLocalized: true } + [mockEntry.uid]: { isLocalized: true }, }; await testClass.makeAPICall(mockApiOptions); @@ -790,9 +761,9 @@ describe('BaseClass', () => { it('should handle create-entries for new entry', async () => { mockApiOptions.entity = 'create-entries' as any; mockApiOptions.apiData = { uid: 'entry-123', title: 'Test Entry' }; - mockApiOptions.additionalInfo = { - cTUid: 'ct-123', - locale: 'en-us' + mockApiOptions.additionalInfo = { + cTUid: 'ct-123', + locale: 'en-us', }; await testClass.makeAPICall(mockApiOptions); @@ -815,10 +786,10 @@ describe('BaseClass', () => { it('should handle publish-entries', async () => { mockApiOptions.entity = 'publish-entries' as any; - mockApiOptions.apiData = { + mockApiOptions.apiData = { entryUid: 'entry-123', environments: ['production'], - locales: ['en-us'] + locales: ['en-us'], }; mockApiOptions.additionalInfo = { cTUid: 'ct-123' }; @@ -830,9 +801,9 @@ describe('BaseClass', () => { it('should handle delete-entries', async () => { mockApiOptions.entity = 'delete-entries' as any; - mockApiOptions.apiData = { + mockApiOptions.apiData = { entryUid: 'entry-123', - cTUid: 'ct-123' + cTUid: 'ct-123', }; mockApiOptions.additionalInfo = { locale: 'en-us' }; @@ -856,9 +827,9 @@ describe('BaseClass', () => { it('should handle create-terms', async () => { mockApiOptions.entity = 'create-terms' as any; - mockApiOptions.apiData = { - name: 'Test Term', - taxonomy_uid: 'taxonomy-123' + mockApiOptions.apiData = { + name: 'Test Term', + taxonomy_uid: 'taxonomy-123', }; await testClass.makeAPICall(mockApiOptions); @@ -900,7 +871,7 @@ describe('BaseClass', () => { reject: sinon.stub(), apiData: { title: 'Test Asset', filename: 'test.jpg' }, additionalInfo: {}, - includeParamOnCompletion: false + includeParamOnCompletion: false, }; }); @@ -918,7 +889,7 @@ describe('BaseClass', () => { it('should handle API errors in update-extensions', async () => { mockApiOptions.entity = 'update-extensions' as any; mockApiOptions.apiData = { uid: 'ext-123', scope: 'global' }; - + const error = new Error('Extension fetch failed'); mockStackClient.extension().fetch.rejects(error); @@ -932,10 +903,10 @@ describe('BaseClass', () => { it('should handle API errors in update-gfs', async () => { mockApiOptions.entity = 'update-gfs' as any; mockApiOptions.apiData = { uid: 'gf-123', title: 'Updated GF' }; - + const mockGF = { title: 'Test GF', - update: sinon.stub().rejects(new Error('Update failed')) + update: sinon.stub().rejects(new Error('Update failed')), }; mockStackClient.globalField().fetch.resolves(mockGF); @@ -949,10 +920,10 @@ describe('BaseClass', () => { it('should handle API errors in update-labels', async () => { mockApiOptions.entity = 'update-labels' as any; mockApiOptions.apiData = { uid: 'label-123', parent: 'parent-123' }; - + const mockLabel = { parent: 'old-parent', - update: sinon.stub().rejects(new Error('Label update failed')) + update: sinon.stub().rejects(new Error('Label update failed')), }; mockStackClient.label().fetch.resolves(mockLabel); @@ -974,29 +945,33 @@ describe('BaseClass', () => { { uid: 'item2', title: 'Item 2' }, { uid: 'item3', title: 'Item 3' }, { uid: 'item4', title: 'Item 4' }, - { uid: 'item5', title: 'Item 5' } + { uid: 'item5', title: 'Item 5' }, ] as any[]; mockApiParams = { entity: 'create-assets', uid: 'test-uid', resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; }); it('should handle custom promise handler with errors', async () => { - const customHandler = sinon.stub() - .onFirstCall().resolves({ success: true }) - .onSecondCall().rejects(new Error('Handler error')) - .onThirdCall().resolves({ success: true }); - + const customHandler = sinon + .stub() + .onFirstCall() + .resolves({ success: true }) + .onSecondCall() + .rejects(new Error('Handler error')) + .onThirdCall() + .resolves({ success: true }); + const env = { apiContent: mockApiContent.slice(0, 3), apiParams: mockApiParams, processName: 'test-process', indexerCount: 1, currentIndexer: 1, - concurrencyLimit: 2 + concurrencyLimit: 2, }; await testClass.makeConcurrentCall(env, customHandler); @@ -1015,7 +990,7 @@ describe('BaseClass', () => { processName: 'test-process', indexerCount: 1, currentIndexer: 1, - concurrencyLimit: 2 + concurrencyLimit: 2, }; await testClass.makeConcurrentCall(env); @@ -1025,14 +1000,14 @@ describe('BaseClass', () => { it('should handle large batches with high concurrency', async () => { const largeContent = Array.from({ length: 20 }, (_, i) => ({ uid: `item${i}`, title: `Item ${i}` })); - + const env = { apiContent: largeContent, apiParams: mockApiParams, processName: 'test-process', indexerCount: 1, currentIndexer: 1, - concurrencyLimit: 5 + concurrencyLimit: 5, }; await testClass.makeConcurrentCall(env); @@ -1042,14 +1017,14 @@ describe('BaseClass', () => { it('should handle isLastRequest correctly', async () => { const customHandler = sinon.stub().resolves({ success: true }); - + const env = { apiContent: mockApiContent.slice(0, 3), apiParams: mockApiParams, processName: 'test-process', indexerCount: 1, currentIndexer: 1, - concurrencyLimit: 2 + concurrencyLimit: 2, }; await testClass.makeConcurrentCall(env, customHandler); @@ -1058,7 +1033,7 @@ describe('BaseClass', () => { const calls = customHandler.getCalls(); expect(calls[0].args[0].isLastRequest).to.be.false; // First item in first batch expect(calls[1].args[0].isLastRequest).to.be.false; // Second item in first batch - expect(calls[2].args[0].isLastRequest).to.be.true; // First item in second batch (last batch) + expect(calls[2].args[0].isLastRequest).to.be.true; // First item in second batch (last batch) }); }); @@ -1074,14 +1049,8 @@ describe('BaseClass', () => { it('should handle execution time display when disabled', async () => { mockImportConfig.modules.assets.displayExecutionTime = false; - - await testClass.logMsgAndWaitIfRequired( - 'test-process', - Date.now() - 500, - 5, - 2, - true - ); + + await testClass.logMsgAndWaitIfRequired('test-process', Date.now() - 500, 5, 2, true); expect(consoleLogStub.called).to.be.false; }); @@ -1093,7 +1062,7 @@ describe('BaseClass', () => { start - 50, // 50ms execution time 5, 2, - true + true, ); const end = Date.now(); @@ -1107,7 +1076,7 @@ describe('BaseClass', () => { start - 5000, // 5000ms execution time 5, 2, - true + true, ); const end = Date.now(); @@ -1118,13 +1087,7 @@ describe('BaseClass', () => { const originalContext = testClass.importConfig.context; testClass.importConfig.context = undefined as any; - await testClass.logMsgAndWaitIfRequired( - 'test-process', - Date.now() - 500, - 5, - 2, - true - ); + await testClass.logMsgAndWaitIfRequired('test-process', Date.now() - 500, 5, 2, true); // Should not throw error expect(true).to.be.true; @@ -1137,14 +1100,14 @@ describe('BaseClass', () => { it('should handle makeConcurrentCall with empty batches', async () => { const env = { apiContent: [] as any[], - apiParams: { + apiParams: { entity: 'create-assets' as any, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }, processName: 'test', indexerCount: 1, - currentIndexer: 1 + currentIndexer: 1, }; await testClass.makeConcurrentCall(env); @@ -1154,14 +1117,14 @@ describe('BaseClass', () => { it('should handle makeConcurrentCall with null apiContent', async () => { const env = { apiContent: null as any, - apiParams: { + apiParams: { entity: 'create-assets' as any, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }, processName: 'test', indexerCount: 1, - currentIndexer: 1 + currentIndexer: 1, }; await testClass.makeConcurrentCall(env); @@ -1173,7 +1136,7 @@ describe('BaseClass', () => { entity: 'create-assets' as any, apiData: { title: 'Test' }, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; // Should not throw error @@ -1195,11 +1158,11 @@ describe('BaseClass', () => { apiParams: { entity: 'create-assets' as any, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }, processName: 'test', indexerCount: 1, - currentIndexer: 1 + currentIndexer: 1, }; await testClass.makeConcurrentCall(env, undefined); @@ -1212,11 +1175,11 @@ describe('BaseClass', () => { apiParams: { entity: 'create-assets' as any, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }, processName: 'test', indexerCount: 1, - currentIndexer: 1 + currentIndexer: 1, }; await testClass.makeConcurrentCall(env, null as any); @@ -1228,7 +1191,7 @@ describe('BaseClass', () => { apiData: { title: 'Test' }, resolve: sinon.stub(), reject: sinon.stub(), - additionalInfo: undefined as any + additionalInfo: undefined as any, }; await testClass.makeAPICall(apiOptions as any); @@ -1241,11 +1204,11 @@ describe('BaseClass', () => { apiData: { title: 'Test' }, resolve: sinon.stub(), reject: sinon.stub(), - additionalInfo: null as any + additionalInfo: null as any, }; await testClass.makeAPICall(apiOptions as any); expect(apiOptions.resolve.calledOnce).to.be.true; }); }); -}); \ No newline at end of file +}); diff --git a/packages/contentstack-import/test/unit/import/modules/content-types.test.ts b/packages/contentstack-import/test/unit/import/modules/content-types.test.ts index 87c197646e..6c9d699605 100644 --- a/packages/contentstack-import/test/unit/import/modules/content-types.test.ts +++ b/packages/contentstack-import/test/unit/import/modules/content-types.test.ts @@ -21,7 +21,7 @@ describe('ImportContentTypes', () => { fsUtilStub = { readFile: sinon.stub(), writeFile: sinon.stub(), - makeDirectory: sinon.stub().resolves() + makeDirectory: sinon.stub().resolves(), }; sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); @@ -35,19 +35,18 @@ describe('ImportContentTypes', () => { contentType: sinon.stub().returns({ create: sinon.stub().resolves({ uid: 'ct-123', title: 'Test CT' }), update: sinon.stub().resolves({ uid: 'ct-123', title: 'Updated CT' }), - fetch: sinon.stub().resolves({ uid: 'ct-123', title: 'Fetched CT' }) + fetch: sinon.stub().resolves({ uid: 'ct-123', title: 'Fetched CT' }), }), globalField: sinon.stub().returns({ update: sinon.stub().resolves({ uid: 'gf-123', title: 'Test GF' }), - fetch: sinon.stub().resolves({ uid: 'gf-123', title: 'Fetched GF' }) - }) + fetch: sinon.stub().resolves({ uid: 'gf-123', title: 'Fetched GF' }), + }), }; mockImportConfig = { apiKey: 'test', contentDir: '/test/content', data: '/test/content', - contentVersion: 1, region: 'us', master_locale: { code: 'en-us' }, masterLocale: { code: 'en-us' }, @@ -60,17 +59,17 @@ describe('ImportContentTypes', () => { sessionId: 'session-123', apiKey: 'test', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, modules: { types: ['content-types'], - 'content-types': { + 'content-types': { dirName: 'content_types', validKeys: ['title', 'uid', 'schema'], apiConcurrency: 5, writeConcurrency: 3, fileName: 'content_types.json', - limit: 100 + limit: 100, }, 'global-fields': { dirName: 'global_fields', @@ -78,8 +77,8 @@ describe('ImportContentTypes', () => { apiConcurrency: 5, writeConcurrency: 1, fileName: 'globalfields.json', - limit: 100 - } + limit: 100, + }, }, backupDir: '/test/backup', cliLogsPath: '/test/logs', @@ -91,28 +90,30 @@ describe('ImportContentTypes', () => { selectedModules: ['content-types'], skipAudit: false, preserveStackVersion: false, - 'exclude-global-modules': false + 'exclude-global-modules': false, } as any; importContentTypes = new ImportContentTypes({ importConfig: mockImportConfig as any, stackAPIClient: mockStackClient, - moduleName: 'content-types' + moduleName: 'content-types', }); makeConcurrentCallStub = sinon.stub(importContentTypes as any, 'makeConcurrentCall').resolves(); - sinon.stub(importContentTypes as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importContentTypes as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importContentTypes as any, 'createNestedProgress').returns({ addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }); - sinon.stub(importContentTypes as any, 'initializeProgress').callsFake(function() { + sinon.stub(importContentTypes as any, 'initializeProgress').callsFake(function () { return this.createNestedProgress(this.currentModuleName); }); sinon.stub(importContentTypes as any, 'completeProgress').resolves(); @@ -132,9 +133,9 @@ describe('ImportContentTypes', () => { expect((importContentTypes as any)['client']).to.equal(mockStackClient); }); - it('should set context module to content-types', () => { - expect(importContentTypes['importConfig'].context.module).to.equal('content-types'); - }); + it('should set context module to content-types', () => { + expect(importContentTypes['importConfig'].context.module).to.equal('content-types'); + }); it('should initialize paths correctly', () => { expect(importContentTypes['cTsFolderPath']).to.include('content_types'); @@ -170,7 +171,7 @@ describe('ImportContentTypes', () => { const instance = new ImportContentTypes({ importConfig: config as any, stackAPIClient: mockStackClient, - moduleName: 'content-types' + moduleName: 'content-types', }); expect(instance['reqConcurrency']).to.equal(2); }); @@ -184,17 +185,19 @@ describe('ImportContentTypes', () => { sinon.stub(importContentTypes as any, 'analyzeImportData').callsFake(async () => { (importContentTypes as any).cTs = []; }); - sinon.stub(importContentTypes as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importContentTypes as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importContentTypes as any, 'createNestedProgress').returns({ addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }); - sinon.stub(importContentTypes as any, 'initializeProgress').callsFake(function() { + sinon.stub(importContentTypes as any, 'initializeProgress').callsFake(function () { return this.createNestedProgress(this.currentModuleName); }); sinon.stub(importContentTypes as any, 'completeProgress').resolves(); @@ -211,17 +214,19 @@ describe('ImportContentTypes', () => { sinon.stub(importContentTypes as any, 'analyzeImportData').callsFake(async () => { (importContentTypes as any).cTs = []; }); - sinon.stub(importContentTypes as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importContentTypes as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importContentTypes as any, 'createNestedProgress').returns({ addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }); - sinon.stub(importContentTypes as any, 'initializeProgress').callsFake(function() { + sinon.stub(importContentTypes as any, 'initializeProgress').callsFake(function () { return this.createNestedProgress(this.currentModuleName); }); sinon.stub(importContentTypes as any, 'completeProgress').resolves(); @@ -234,7 +239,7 @@ describe('ImportContentTypes', () => { it('should process content types when available', async () => { const mockCTs = [ { uid: 'ct1', title: 'Content Type 1', schema: [] as any }, - { uid: 'ct2', title: 'Content Type 2', schema: [] as any } + { uid: 'ct2', title: 'Content Type 2', schema: [] as any }, ]; fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); @@ -352,12 +357,12 @@ describe('ImportContentTypes', () => { it('should update pending global fields when available', async () => { (importContentTypes as any).handlePendingGlobalFields.restore(); - + const mockCTs = [{ uid: 'ct1', title: 'CT 1', schema: [] as any }]; const pendingGFs = ['gf1', 'gf2']; const mockGFs = [ { uid: 'gf1', schema: [] as any }, - { uid: 'gf2', schema: [] as any } + { uid: 'gf2', schema: [] as any }, ]; fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); @@ -424,7 +429,7 @@ describe('ImportContentTypes', () => { const onReject = makeConcurrentCallStub.firstCall.args[0].apiParams.reject; onReject({ error: { errorCode: 115, errors: { uid: 'exists' } }, - apiData: { content_type: { uid: 'ct1' } } + apiData: { content_type: { uid: 'ct1' } }, }); // Should not throw, just log @@ -439,7 +444,7 @@ describe('ImportContentTypes', () => { const onReject = makeConcurrentCallStub.firstCall.args[0].apiParams.reject; onReject({ error: { errorCode: 500, message: 'Server error' }, - apiData: { content_type: { uid: 'ct1' } } + apiData: { content_type: { uid: 'ct1' } }, }); // Should handle error gracefully @@ -449,7 +454,7 @@ describe('ImportContentTypes', () => { describe('serializeCTs()', () => { it('should serialize content type correctly', () => { const apiOptions = { - apiData: { uid: 'test_ct', title: 'Test Content Type', schema: [] as any } + apiData: { uid: 'test_ct', title: 'Test Content Type', schema: [] as any }, }; const result = importContentTypes.serializeCTs(apiOptions as any); @@ -461,7 +466,7 @@ describe('ImportContentTypes', () => { it('should use schemaTemplate structure', () => { const apiOptions = { - apiData: { uid: 'ct_uid', title: 'CT Title', schema: [] as any } + apiData: { uid: 'ct_uid', title: 'CT Title', schema: [] as any }, }; const result = importContentTypes.serializeCTs(apiOptions as any); @@ -488,9 +493,9 @@ describe('ImportContentTypes', () => { await importContentTypes.updateCTs(); expect(makeConcurrentCallStub.called).to.be.true; - const callArgs = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update content types' - )?.args[0]; + const callArgs = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update content types')?.args[0]; expect(callArgs.processName).to.equal('Update content types'); expect(callArgs.apiParams.entity).to.equal('update-cts'); }); @@ -500,9 +505,9 @@ describe('ImportContentTypes', () => { await importContentTypes.updateCTs(); - const onSuccess = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update content types' - )?.args[0].apiParams.resolve; + const onSuccess = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update content types')?.args[0].apiParams.resolve; expect(() => { onSuccess({ response: {}, apiData: { uid: 'ct1' } }); @@ -514,9 +519,9 @@ describe('ImportContentTypes', () => { await importContentTypes.updateCTs(); - const onReject = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update content types' - )?.args[0].apiParams.reject; + const onReject = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update content types')?.args[0].apiParams.reject; // onReject calls handleAndLogError which doesn't throw, it logs the error // So we just verify it can be called without throwing @@ -530,7 +535,7 @@ describe('ImportContentTypes', () => { beforeEach(() => { mockStackClient.contentType.returns({ uid: 'test_ct', - title: 'Test CT' + title: 'Test CT', }); updateFieldRulesStub.returns([]); lookupExtensionStub.returns(undefined); @@ -542,7 +547,7 @@ describe('ImportContentTypes', () => { uid: 'ct1', title: 'CT 1', schema: [] as any, - field_rules: [{ conditions: [] as any }] + field_rules: [{ conditions: [] as any }], }; updateFieldRulesStub.returns([{ conditions: [] as any }]); @@ -558,7 +563,7 @@ describe('ImportContentTypes', () => { uid: 'ct1', title: 'CT 1', schema: [] as any, - field_rules: [] as any + field_rules: [] as any, }; updateFieldRulesStub.returns([]); @@ -603,11 +608,11 @@ describe('ImportContentTypes', () => { importContentTypes['pendingGFs'] = ['gf1', 'gf2']; importContentTypes['gFs'] = [ { uid: 'gf1', title: 'GF 1', schema: [] as any }, - { uid: 'gf2', title: 'GF 2', schema: [] as any } + { uid: 'gf2', title: 'GF 2', schema: [] as any }, ]; fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns([ { uid: 'gf1', title: 'GF 1', schema: [] as any }, - { uid: 'gf2', title: 'GF 2', schema: [] as any } + { uid: 'gf2', title: 'GF 2', schema: [] as any }, ]); fsUtilStub.readFile.withArgs(sinon.match(/pending_global_fields\.js/)).returns(['gf1', 'gf2']); }); @@ -615,9 +620,9 @@ describe('ImportContentTypes', () => { it('should process pending global fields', async () => { await importContentTypes.updatePendingGFs(); - const callArgs = makeConcurrentCallStub.getCalls().find((call: any) => - (call.args[0] as any)?.processName === 'Update pending global fields' - )?.args[0] as any; + const callArgs = makeConcurrentCallStub + .getCalls() + .find((call: any) => (call.args[0] as any)?.processName === 'Update pending global fields')?.args[0] as any; expect(callArgs).to.not.be.undefined; expect(callArgs?.processName).to.equal('Update pending global fields'); expect(callArgs?.apiParams?.entity).to.equal('update-gfs'); @@ -626,9 +631,9 @@ describe('ImportContentTypes', () => { it('should transform pending GFs to apiContent format', async () => { await importContentTypes.updatePendingGFs(); - const callArgs = makeConcurrentCallStub.getCalls().find((call: any) => - (call.args[0] as any)?.processName === 'Update pending global fields' - )?.args[0] as any; + const callArgs = makeConcurrentCallStub + .getCalls() + .find((call: any) => (call.args[0] as any)?.processName === 'Update pending global fields')?.args[0] as any; expect(callArgs).to.not.be.undefined; const apiContent = callArgs?.apiContent; expect(apiContent).to.have.lengthOf(2); @@ -640,9 +645,9 @@ describe('ImportContentTypes', () => { importContentTypes['pendingGFs'] = ['gf1']; await importContentTypes.updatePendingGFs(); - const callArgs = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update pending global fields' - )?.args[0] as any; + const callArgs = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update pending global fields')?.args[0] as any; expect(callArgs).to.not.be.undefined; const onSuccess = callArgs?.apiParams?.resolve; expect(onSuccess).to.be.a('function'); @@ -656,9 +661,9 @@ describe('ImportContentTypes', () => { importContentTypes['pendingGFs'] = ['gf1']; await importContentTypes.updatePendingGFs(); - const callArgs = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update pending global fields' - )?.args[0] as any; + const callArgs = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update pending global fields')?.args[0] as any; expect(callArgs).to.not.be.undefined; const onReject = callArgs?.apiParams?.reject; expect(onReject).to.be.a('function'); @@ -673,7 +678,7 @@ describe('ImportContentTypes', () => { beforeEach(() => { mockStackClient.globalField.returns({ uid: 'test_gf', - title: 'Test GF' + title: 'Test GF', }); lookupExtensionStub.returns(undefined); }); @@ -749,9 +754,9 @@ describe('ImportContentTypes', () => { await importContentTypes.updatePendingExtensions(); - const onSuccess = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'update extensions' - )?.args[0].apiParams.resolve; + const onSuccess = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'update extensions')?.args[0].apiParams.resolve; expect(() => { onSuccess({ response: { title: 'Extension 1' }, apiData: { uid: 'ext1', title: 'Extension 1' } }); @@ -764,9 +769,9 @@ describe('ImportContentTypes', () => { await importContentTypes.updatePendingExtensions(); - const onReject = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'update extensions' - )?.args[0].apiParams.reject; + const onReject = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'update extensions')?.args[0].apiParams.reject; expect(() => { onReject({ error: { errors: { title: 'exists' } }, apiData: { uid: 'ext1' } }); @@ -779,9 +784,9 @@ describe('ImportContentTypes', () => { await importContentTypes.updatePendingExtensions(); - const onReject = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'update extensions' - )?.args[0].apiParams.reject; + const onReject = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'update extensions')?.args[0].apiParams.reject; expect(() => { onReject({ error: { message: 'Server error' }, apiData: { uid: 'ext1' } }); @@ -794,9 +799,9 @@ describe('ImportContentTypes', () => { await importContentTypes.updatePendingExtensions(); - const callArgs = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'update extensions' - )?.args[0]; + const callArgs = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'update extensions')?.args[0]; expect(callArgs.concurrencyLimit).to.be.a('number'); }); }); @@ -879,14 +884,16 @@ describe('ImportContentTypes', () => { it('should complete full content types import flow', async () => { const mockCTs = [ { uid: 'ct1', title: 'Content Type 1', schema: [] as any }, - { uid: 'ct2', title: 'Content Type 2', schema: [] as any } + { uid: 'ct2', title: 'Content Type 2', schema: [] as any }, ]; fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns([]); fsUtilStub.readFile.withArgs(sinon.match(/pending_global_fields\.js/)).returns([]); fsUtilStub.readFile.withArgs(sinon.match(/pending_extensions\.js/)).returns([]); - fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: { ext1: 'uid1' } }); + fsUtilStub.readFile + .withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)) + .returns({ extension_uid: { ext1: 'uid1' } }); fsUtilStub.readFile.withArgs(sinon.match(/taxonomies.*success\.json/)).returns({ tax1: {} }); fsUtilStub.readFile.withArgs(sinon.match(/success\.json/)).returns({}); @@ -907,12 +914,12 @@ describe('ImportContentTypes', () => { it('should handle complete flow with pending global fields', async () => { (importContentTypes as any).handlePendingGlobalFields.restore(); - + const mockCTs = [{ uid: 'ct1', title: 'CT 1', schema: [] as any }]; const pendingGFs = ['gf1', 'gf2']; const mockGFs = [ { uid: 'gf1', schema: [] as any }, - { uid: 'gf2', schema: [] as any } + { uid: 'gf2', schema: [] as any }, ]; fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); @@ -934,7 +941,7 @@ describe('ImportContentTypes', () => { const mockExtensions = [{ uid: 'ext1', title: 'Extension 1' }]; (importContentTypes as any).handlePendingExtensions.restore(); - + fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns([]); fsUtilStub.readFile.withArgs(sinon.match(/pending_global_fields\.js/)).returns([]); @@ -954,7 +961,7 @@ describe('ImportContentTypes', () => { describe('Additional Branch Coverage Tests', () => { it('should handle different error conditions in seedCTs onReject', async () => { const mockCTs = [{ uid: 'ct1', title: 'Content Type 1' }]; - + fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns([]); fsUtilStub.readFile.withArgs(sinon.match(/pending_global_fields\.js/)).returns([]); @@ -966,17 +973,17 @@ describe('ImportContentTypes', () => { await importContentTypes.start(); const onReject = makeConcurrentCallStub.firstCall.args[0].apiParams.reject; - + // Test error with errorCode 115 but different error structure onReject({ error: { errorCode: 115, errors: { title: 'Title already exists' } }, - apiData: { content_type: { uid: 'ct1' } } + apiData: { content_type: { uid: 'ct1' } }, }); // Test error with errorCode 115 but different error structure onReject({ error: { errorCode: 115, errors: { uid: 'UID already exists' } }, - apiData: { content_type: { uid: 'ct1' } } + apiData: { content_type: { uid: 'ct1' } }, }); expect(makeConcurrentCallStub.called).to.be.true; @@ -984,14 +991,14 @@ describe('ImportContentTypes', () => { it('should handle different conditions in updatePendingGFs', async () => { (importContentTypes as any).handlePendingGlobalFields.restore(); - + const mockCTs = [{ uid: 'ct1', title: 'Content Type 1' }]; const mockPendingGFs = ['gf1', 'gf2']; const mockGFs = [ { uid: 'gf1', title: 'Global Field 1' }, - { uid: 'gf2', title: 'Global Field 2' } + { uid: 'gf2', title: 'Global Field 2' }, ]; - + fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/pending_global_fields\.js/)).returns(mockPendingGFs); @@ -1006,21 +1013,21 @@ describe('ImportContentTypes', () => { expect(makeConcurrentCallStub.callCount).to.be.greaterThanOrEqual(3); const updatePendingGFsCall = makeConcurrentCallStub.getCall(2); expect(updatePendingGFsCall).to.not.be.null; - + if (updatePendingGFsCall) { const onSuccess = updatePendingGFsCall.args[0].apiParams.resolve; const onReject = updatePendingGFsCall.args[0].apiParams.reject; - + // Test onSuccess with undefined uid onSuccess({ response: { uid: 'gf1' }, - apiData: { uid: undefined } + apiData: { uid: undefined }, }); // Test onReject with undefined uid onReject({ error: { message: 'Update failed' }, - apiData: { uid: undefined } + apiData: { uid: undefined }, }); } }); @@ -1028,7 +1035,7 @@ describe('ImportContentTypes', () => { it('should handle different conditions in updatePendingExtensions', async () => { const mockCTs = [{ uid: 'ct1', title: 'Content Type 1' }]; const mockExtensions = [{ uid: 'ext1', title: 'Extension 1' }]; - + fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns([]); fsUtilStub.readFile.withArgs(sinon.match(/pending_global_fields\.js/)).returns([]); @@ -1041,25 +1048,25 @@ describe('ImportContentTypes', () => { const onSuccess = makeConcurrentCallStub.lastCall.args[0].apiParams.resolve; const onReject = makeConcurrentCallStub.lastCall.args[0].apiParams.reject; - + // Test onSuccess with undefined uid and title onSuccess({ response: { title: 'Updated Extension' }, - apiData: { uid: undefined, title: undefined } + apiData: { uid: undefined, title: undefined }, }); // Test onReject with title error and skipExisting true importContentTypes['importConfig'].skipExisting = true; onReject({ error: { errors: { title: 'Title already exists' } }, - apiData: { uid: 'ext1' } + apiData: { uid: 'ext1' }, }); // Test onReject with title error and skipExisting false importContentTypes['importConfig'].skipExisting = false; onReject({ error: { errors: { title: 'Title already exists' } }, - apiData: { uid: 'ext1' } + apiData: { uid: 'ext1' }, }); expect(makeConcurrentCallStub.called).to.be.true; @@ -1067,7 +1074,7 @@ describe('ImportContentTypes', () => { it('should handle null apiContent in updatePendingExtensions', async () => { const mockCTs = [{ uid: 'ct1', title: 'Content Type 1' }]; - + fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns([]); fsUtilStub.readFile.withArgs(sinon.match(/pending_global_fields\.js/)).returns([]); @@ -1083,7 +1090,7 @@ describe('ImportContentTypes', () => { it('should handle empty array apiContent in updatePendingExtensions', async () => { const mockCTs = [{ uid: 'ct1', title: 'Content Type 1' }]; - + fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns([]); fsUtilStub.readFile.withArgs(sinon.match(/pending_global_fields\.js/)).returns([]); @@ -1100,7 +1107,7 @@ describe('ImportContentTypes', () => { it('should handle onSuccess with different response structure in updatePendingExtensions', async () => { const mockCTs = [{ uid: 'ct1', title: 'Content Type 1' }]; const mockExtensions = [{ uid: 'ext1', title: 'Extension 1' }]; - + fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns([]); fsUtilStub.readFile.withArgs(sinon.match(/pending_global_fields\.js/)).returns([]); @@ -1112,11 +1119,11 @@ describe('ImportContentTypes', () => { await importContentTypes.start(); const onSuccess = makeConcurrentCallStub.lastCall.args[0].apiParams.resolve; - + // Test onSuccess with response that has no title property onSuccess({ response: { uid: 'ext1' }, - apiData: { uid: 'ext1', title: 'Extension 1' } + apiData: { uid: 'ext1', title: 'Extension 1' }, }); expect(makeConcurrentCallStub.called).to.be.true; @@ -1125,7 +1132,7 @@ describe('ImportContentTypes', () => { it('should handle onReject with different error structures in updatePendingExtensions', async () => { const mockCTs = [{ uid: 'ct1', title: 'Content Type 1' }]; const mockExtensions = [{ uid: 'ext1', title: 'Extension 1' }]; - + fsUtilStub.readFile.withArgs(sinon.match(/schema\.json/)).returns(mockCTs); fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns([]); fsUtilStub.readFile.withArgs(sinon.match(/pending_global_fields\.js/)).returns([]); @@ -1137,17 +1144,17 @@ describe('ImportContentTypes', () => { await importContentTypes.start(); const onReject = makeConcurrentCallStub.lastCall.args[0].apiParams.reject; - + // Test onReject with error that has no errors property onReject({ error: { message: 'Server error' }, - apiData: { uid: 'ext1' } + apiData: { uid: 'ext1' }, }); // Test onReject with error that has errors but no title onReject({ error: { errors: { uid: 'UID already exists' } }, - apiData: { uid: 'ext1' } + apiData: { uid: 'ext1' }, }); expect(makeConcurrentCallStub.called).to.be.true; diff --git a/packages/contentstack-import/test/unit/import/modules/custom-roles.test.ts b/packages/contentstack-import/test/unit/import/modules/custom-roles.test.ts index 440439b035..162a276a78 100644 --- a/packages/contentstack-import/test/unit/import/modules/custom-roles.test.ts +++ b/packages/contentstack-import/test/unit/import/modules/custom-roles.test.ts @@ -44,7 +44,6 @@ describe('ImportCustomRoles', () => { apiKey: 'test', backupDir: '/test/backup', data: '/test/content', - contentVersion: 1, region: 'us', fetchConcurrency: 2, context: { @@ -74,12 +73,14 @@ describe('ImportCustomRoles', () => { moduleName: 'custom-roles', }); - sinon.stub(importCustomRoles as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importCustomRoles as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importCustomRoles as any, 'analyzeCustomRoles').resolves([1]); const mockProgress = { - updateStatus: sinon.stub() + updateStatus: sinon.stub(), }; sinon.stub(importCustomRoles as any, 'createSimpleProgress').returns(mockProgress); sinon.stub(importCustomRoles as any, 'prepareForImport').resolves(); @@ -133,26 +134,28 @@ describe('ImportCustomRoles', () => { it('should process custom roles when folder exists', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - - sinon.stub(importCustomRoles as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importCustomRoles as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importCustomRoles as any, 'getLocalesUidMap').resolves(); sinon.stub(importCustomRoles as any, 'completeProgress').resolves(); const mockProgress = { updateStatus: sinon.stub() }; sinon.stub(importCustomRoles as any, 'createSimpleProgress').returns(mockProgress); - + const mockRoles = { role1: { uid: 'role1', name: 'Role 1', rules: [] as any } }; fileHelperStub.fileExistsSync.withArgs(sinon.match(/roles$/)).returns(true); fileHelperStub.fileExistsSync.withArgs(sinon.match(/uid-mapping\.json/)).returns(false); fsUtilStub.readFile.withArgs(sinon.match(/roles\.json/)).returns(mockRoles); fsUtilStub.readFile.withArgs(sinon.match(/roles-locales\.json/)).returns({}); - + makeConcurrentCallStub = sinon.stub(importCustomRoles as any, 'makeConcurrentCall').resolves(); await importCustomRoles.start(); @@ -163,21 +166,23 @@ describe('ImportCustomRoles', () => { it('should load existing UID mapper when file exists', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - - sinon.stub(importCustomRoles as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importCustomRoles as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importCustomRoles as any, 'getLocalesUidMap').resolves(); sinon.stub(importCustomRoles as any, 'completeProgress').resolves(); const mockProgress = { updateStatus: sinon.stub() }; sinon.stub(importCustomRoles as any, 'createSimpleProgress').returns(mockProgress); makeConcurrentCallStub = sinon.stub(importCustomRoles as any, 'makeConcurrentCall').resolves(); - + const mockRoles = { role1: { uid: 'role1', name: 'Role 1', rules: [] as any } }; const mockUidMapper = { role1: 'mapped-role1' }; @@ -196,21 +201,23 @@ describe('ImportCustomRoles', () => { it('should load environments UID map when available', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - - sinon.stub(importCustomRoles as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importCustomRoles as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importCustomRoles as any, 'getLocalesUidMap').resolves(); sinon.stub(importCustomRoles as any, 'completeProgress').resolves(); const mockProgress = { updateStatus: sinon.stub() }; sinon.stub(importCustomRoles as any, 'createSimpleProgress').returns(mockProgress); makeConcurrentCallStub = sinon.stub(importCustomRoles as any, 'makeConcurrentCall').resolves(); - + const mockRoles = { role1: { uid: 'role1', name: 'Role 1', rules: [] as any } }; const mockEnvMap = { env1: 'mapped-env1' }; @@ -229,21 +236,23 @@ describe('ImportCustomRoles', () => { it('should load entries UID map when available', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - - sinon.stub(importCustomRoles as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importCustomRoles as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importCustomRoles as any, 'getLocalesUidMap').resolves(); sinon.stub(importCustomRoles as any, 'completeProgress').resolves(); const mockProgress = { updateStatus: sinon.stub() }; sinon.stub(importCustomRoles as any, 'createSimpleProgress').returns(mockProgress); makeConcurrentCallStub = sinon.stub(importCustomRoles as any, 'makeConcurrentCall').resolves(); - + const mockRoles = { role1: { uid: 'role1', name: 'Role 1', rules: [] as any } }; const mockEntriesMap = { entry1: 'mapped-entry1' }; @@ -262,21 +271,23 @@ describe('ImportCustomRoles', () => { it('should write success file when custom roles created', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - - sinon.stub(importCustomRoles as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importCustomRoles as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importCustomRoles as any, 'getLocalesUidMap').resolves(); sinon.stub(importCustomRoles as any, 'completeProgress').resolves(); const mockProgress = { updateStatus: sinon.stub() }; sinon.stub(importCustomRoles as any, 'createSimpleProgress').returns(mockProgress); makeConcurrentCallStub = sinon.stub(importCustomRoles as any, 'makeConcurrentCall').resolves(); - + const mockRoles = { role1: { uid: 'role1', name: 'Role 1', rules: [] as any } }; fileHelperStub.fileExistsSync.withArgs(sinon.match(/roles$/)).returns(true); @@ -293,21 +304,23 @@ describe('ImportCustomRoles', () => { it('should write fails file when custom roles failed', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - - sinon.stub(importCustomRoles as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importCustomRoles as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importCustomRoles as any, 'getLocalesUidMap').resolves(); sinon.stub(importCustomRoles as any, 'completeProgress').resolves(); const mockProgress = { updateStatus: sinon.stub() }; sinon.stub(importCustomRoles as any, 'createSimpleProgress').returns(mockProgress); makeConcurrentCallStub = sinon.stub(importCustomRoles as any, 'makeConcurrentCall').resolves(); - + const mockRoles = { role1: { uid: 'role1', name: 'Role 1', rules: [] as any } }; fileHelperStub.fileExistsSync.withArgs(sinon.match(/roles$/)).returns(true); @@ -330,7 +343,7 @@ describe('ImportCustomRoles', () => { sinon.stub(fsUtil, 'writeFile'); sinon.stub(fsUtil, 'makeDirectory'); sinon.stub(fileHelper, 'fileExistsSync'); - + const mockLocales = [ { code: 'en-us', uid: 'locale1' }, { code: 'fr-fr', uid: 'locale2' }, @@ -362,7 +375,7 @@ describe('ImportCustomRoles', () => { sinon.stub(fsUtil, 'writeFile'); sinon.stub(fsUtil, 'makeDirectory'); sinon.stub(fileHelper, 'fileExistsSync'); - + const findStub = sinon.stub().resolves({ items: [] }); const localeQueryStub = sinon.stub().returns({ find: findStub, @@ -653,21 +666,23 @@ describe('ImportCustomRoles', () => { describe('Additional Branch Coverage Tests', () => { it('should log when customRolesUidMapper has items', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - - sinon.stub(importCustomRoles as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importCustomRoles as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importCustomRoles as any, 'getLocalesUidMap').resolves(); sinon.stub(importCustomRoles as any, 'completeProgress').resolves(); const mockProgress = { updateStatus: sinon.stub() }; sinon.stub(importCustomRoles as any, 'createSimpleProgress').returns(mockProgress); makeConcurrentCallStub = sinon.stub(importCustomRoles as any, 'makeConcurrentCall').resolves(); - + const mockRoles = { role1: { uid: 'role1', name: 'Role 1', rules: [] as any } }; const mockUidMapper = { existingRole: 'existing-uid' }; @@ -686,21 +701,23 @@ describe('ImportCustomRoles', () => { it('should log when environmentsUidMap has items', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - - sinon.stub(importCustomRoles as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importCustomRoles as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importCustomRoles as any, 'getLocalesUidMap').resolves(); sinon.stub(importCustomRoles as any, 'completeProgress').resolves(); const mockProgress = { updateStatus: sinon.stub() }; sinon.stub(importCustomRoles as any, 'createSimpleProgress').returns(mockProgress); makeConcurrentCallStub = sinon.stub(importCustomRoles as any, 'makeConcurrentCall').resolves(); - + const mockRoles = { role1: { uid: 'role1', name: 'Role 1', rules: [] as any } }; const mockEnvMapper = { env1: 'env-uid-1', env2: 'env-uid-2' }; @@ -719,21 +736,23 @@ describe('ImportCustomRoles', () => { it('should log when entriesUidMap has items', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - - sinon.stub(importCustomRoles as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importCustomRoles as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importCustomRoles as any, 'getLocalesUidMap').resolves(); sinon.stub(importCustomRoles as any, 'completeProgress').resolves(); const mockProgress = { updateStatus: sinon.stub() }; sinon.stub(importCustomRoles as any, 'createSimpleProgress').returns(mockProgress); makeConcurrentCallStub = sinon.stub(importCustomRoles as any, 'makeConcurrentCall').resolves(); - + const mockRoles = { role1: { uid: 'role1', name: 'Role 1', rules: [] as any } }; const mockEntriesMapper = { entry1: 'entry-uid-1', entry2: 'entry-uid-2' }; @@ -1010,7 +1029,7 @@ describe('ImportCustomRoles', () => { describe('Integration Tests', () => { it('should complete full custom roles import flow', async () => { sinon.restore(); - + fsUtilStub = { readFile: sinon.stub(), writeFile: sinon.stub(), @@ -1024,7 +1043,7 @@ describe('ImportCustomRoles', () => { fileExistsSync: sinon.stub(), }; sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockRoles = { role1: { uid: 'role1', name: 'Role 1', rules: [] as any }, role2: { uid: 'role2', name: 'Role 2', rules: [] as any }, @@ -1035,19 +1054,21 @@ describe('ImportCustomRoles', () => { fsUtilStub.readFile.withArgs(sinon.match(/roles\.json/)).returns(mockRoles); fsUtilStub.readFile.withArgs(sinon.match(/roles-locales\.json/)).returns({ locale1: { code: 'en-us' } }); - sinon.stub(importCustomRoles as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importCustomRoles as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importCustomRoles as any, 'analyzeCustomRoles').callsFake(async () => { importCustomRoles['customRoles'] = mockRoles; return [2]; }); sinon.stub(importCustomRoles as any, 'createSimpleProgress').returns({ - updateStatus: sinon.stub() + updateStatus: sinon.stub(), }); sinon.stub(importCustomRoles as any, 'getLocalesUidMap').resolves(); sinon.stub(importCustomRoles as any, 'completeProgress').resolves(); - + makeConcurrentCallStub = sinon.stub(importCustomRoles as any, 'makeConcurrentCall').resolves(); importCustomRoles['createdCustomRoles'] = []; @@ -1055,7 +1076,7 @@ describe('ImportCustomRoles', () => { const prepareForImportStub = sinon.stub(importCustomRoles as any, 'prepareForImport').resolves(); const importCustomRolesStub = sinon.stub(importCustomRoles as any, 'importCustomRoles').resolves(); const handleImportResultsStub = sinon.stub(importCustomRoles as any, 'handleImportResults').resolves(); - + await importCustomRoles.start(); expect(prepareForImportStub.called).to.be.true; diff --git a/packages/contentstack-import/test/unit/import/modules/entries.test.ts b/packages/contentstack-import/test/unit/import/modules/entries.test.ts index d3a99926e4..7fd6818905 100644 --- a/packages/contentstack-import/test/unit/import/modules/entries.test.ts +++ b/packages/contentstack-import/test/unit/import/modules/entries.test.ts @@ -6,7 +6,6 @@ import { FsUtility } from '@contentstack/cli-utilities'; import { fsUtil, fileHelper, MODULE_CONTEXTS } from '../../../../src/utils'; import * as path from 'path'; - const mockData = require('./mock-data/entries/content-types.json'); const mockEntries = require('./mock-data/entries/entries.json'); const mockLocales = require('./mock-data/entries/locales.json'); @@ -49,19 +48,18 @@ describe('EntriesImport', () => { delete: sinon.stub().resolves({ uid: 'deleted-entry-uid' }), publish: sinon.stub().resolves({ uid: 'published-entry-uid' }), query: sinon.stub().returns({ - findOne: sinon.stub().resolves({ items: [{ uid: 'existing-entry-uid', title: 'Existing Entry' }] }) - }) + findOne: sinon.stub().resolves({ items: [{ uid: 'existing-entry-uid', title: 'Existing Entry' }] }), + }), }), fetch: sinon.stub().resolves({ uid: 'ct-uid', schema: [] }), - update: sinon.stub().resolves({ uid: 'updated-ct-uid' }) - }) + update: sinon.stub().resolves({ uid: 'updated-ct-uid' }), + }), }; mockImportConfig = { apiKey: 'test', contentDir: '/test/content', data: '/test/content', - contentVersion: 1, region: 'us', master_locale: { code: 'en-us' }, masterLocale: { code: 'en-us' }, @@ -73,23 +71,23 @@ describe('EntriesImport', () => { sessionId: 'session-123', apiKey: 'test', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, modules: { types: ['entries'], - entries: { + entries: { dirName: 'entries', chunkFileSize: 100, invalidKeys: ['_version', 'created_at', 'updated_at'], - importConcurrency: 5 + importConcurrency: 5, }, 'content-types': { - dirName: 'content_types' + dirName: 'content_types', }, locales: { dirName: 'locales', - fileName: 'locales.json' - } + fileName: 'locales.json', + }, }, backupDir: '/test/backup', cliLogsPath: '/test/logs', @@ -103,13 +101,13 @@ describe('EntriesImport', () => { skipEntriesPublish: false, 'exclude-global-modules': false, replaceExisting: false, - importConcurrency: 5 + importConcurrency: 5, } as any; entriesImport = new EntriesImport({ importConfig: mockImportConfig as any, stackAPIClient: mockStackClient, - moduleName: 'entries' + moduleName: 'entries', }); makeConcurrentCallStub = sinon.stub(entriesImport as any, 'makeConcurrentCall').resolves(); @@ -171,16 +169,16 @@ describe('EntriesImport', () => { entries: { dirName: 'entries', chunkFileSize: 100, - invalidKeys: ['_version', 'created_at', 'updated_at'] + invalidKeys: ['_version', 'created_at', 'updated_at'], // No importConcurrency - } - } + }, + }, }; const entriesImportFallback = new EntriesImport({ importConfig: configWithoutEntriesConcurrency as any, stackAPIClient: mockStackClient, - moduleName: 'entries' + moduleName: 'entries', }); expect(entriesImportFallback['importConcurrency']).to.equal(5); @@ -193,7 +191,7 @@ describe('EntriesImport', () => { mockData.simpleContentType, mockData.contentTypeWithReferences, mockData.contentTypeWithJsonRte, - mockData.contentTypeWithAssets + mockData.contentTypeWithAssets, ]; entriesImport['installedExtensions'] = mockMappers.installedExtensions; }); @@ -204,7 +202,7 @@ describe('EntriesImport', () => { const onSuccess = options.apiParams.resolve; onSuccess({ response: { uid: 'ct-uid' }, - apiData: { uid: 'ct-uid' } + apiData: { uid: 'ct-uid' }, }); }); @@ -219,7 +217,7 @@ describe('EntriesImport', () => { const onReject = options.apiParams.reject; onReject({ error: new Error('Content type processing failed'), - apiData: { uid: 'ct-uid' } + apiData: { uid: 'ct-uid' }, }); }); @@ -239,16 +237,16 @@ describe('EntriesImport', () => { uid: 'mandatory_field', data_type: 'text', display_name: 'Mandatory Field', - mandatory: true - } - ] + mandatory: true, + }, + ], }; const apiOptions = { apiData: contentTypeWithReferences, entity: 'update-cts' as const, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; const result = entriesImport['serializeUpdateCTs'](apiOptions); @@ -267,16 +265,16 @@ describe('EntriesImport', () => { uid: 'mandatory_field', data_type: 'text', display_name: 'Mandatory Field', - mandatory: true - } - ] + mandatory: true, + }, + ], }; const apiOptions = { apiData: contentTypeWithJsonRte, entity: 'update-cts' as const, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; const result = entriesImport['serializeUpdateCTs'](apiOptions); @@ -297,7 +295,7 @@ describe('EntriesImport', () => { data_type: 'text', display_name: 'Title', mandatory: true, - unique: true + unique: true, }, { uid: 'rte_field', @@ -305,24 +303,24 @@ describe('EntriesImport', () => { display_name: 'RTE Field', field_metadata: { rich_text_type: true, - embed_entry: true + embed_entry: true, }, - reference_to: ['simple_ct'] + reference_to: ['simple_ct'], }, { uid: 'mandatory_field', data_type: 'text', display_name: 'Mandatory Field', - mandatory: true - } - ] + mandatory: true, + }, + ], }; const apiOptions = { apiData: contentTypeWithRte, entity: 'update-cts' as const, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; const result = entriesImport['serializeUpdateCTs'](apiOptions); @@ -338,7 +336,7 @@ describe('EntriesImport', () => { apiData: mockData.simpleContentType, entity: 'update-cts' as const, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; const result = entriesImport['serializeUpdateCTs'](apiOptions); @@ -356,22 +354,22 @@ describe('EntriesImport', () => { uid: 'mandatory_field', data_type: 'text', display_name: 'Mandatory Field', - mandatory: true - } + mandatory: true, + }, ], field_rules: [ { conditions: [{ operand_field: 'title', operator: 'equals', value: 'test' }], - actions: [{ operand_field: 'description', action: 'show' }] - } - ] + actions: [{ operand_field: 'description', action: 'show' }], + }, + ], }; const apiOptions = { apiData: contentTypeWithFieldRules, entity: 'update-cts' as const, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; const result = entriesImport['serializeUpdateCTs'](apiOptions); @@ -389,22 +387,22 @@ describe('EntriesImport', () => { data_type: 'text', display_name: 'Title', mandatory: true, - unique: true + unique: true, }, { uid: 'mandatory_field', data_type: 'text', display_name: 'Mandatory Field', - mandatory: true - } - ] + mandatory: true, + }, + ], }; const apiOptions = { apiData: contentTypeWithMandatory, entity: 'update-cts' as const, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; entriesImport['serializeUpdateCTs'](apiOptions); @@ -424,7 +422,7 @@ describe('EntriesImport', () => { const onSuccess = options.apiParams.resolve; onSuccess({ response: { uid: 'ct-uid' }, - apiData: { uid: 'ct-uid' } + apiData: { uid: 'ct-uid' }, }); }); @@ -438,7 +436,7 @@ describe('EntriesImport', () => { const onReject = options.apiParams.reject; onReject({ error: new Error('Content type update failed'), - apiData: { uid: 'ct-uid' } + apiData: { uid: 'ct-uid' }, }); }); @@ -458,7 +456,7 @@ describe('EntriesImport', () => { apiData: mockData.contentTypeWithReferences, entity: 'update-cts' as const, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; const result = entriesImport['serializeUpdateCTsWithRef'](apiOptions); @@ -473,16 +471,16 @@ describe('EntriesImport', () => { field_rules: [ { conditions: [{ operand_field: 'title', operator: 'equals', value: 'test' }], - actions: [{ operand_field: 'description', action: 'show' }] - } - ] + actions: [{ operand_field: 'description', action: 'show' }], + }, + ], }; const apiOptions = { apiData: contentTypeWithFieldRules, entity: 'update-cts' as const, resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; const result = entriesImport['serializeUpdateCTsWithRef'](apiOptions); @@ -495,8 +493,8 @@ describe('EntriesImport', () => { beforeEach(() => { entriesImport['cTs'] = [mockData.contentTypeWithFieldRules]; entriesImport['entriesUidMapper'] = { - 'entry_uid_1': 'new_entry_uid_1', - 'entry_uid_2': 'new_entry_uid_2' + entry_uid_1: 'new_entry_uid_1', + entry_uid_2: 'new_entry_uid_2', }; fsUtilityReadFileStub.callsFake((path) => { if (path.includes('field_rules_uid.json')) { @@ -513,11 +511,11 @@ describe('EntriesImport', () => { const mockContentTypeResponse = { uid: 'field_rules_ct', field_rules: mockData.contentTypeWithFieldRules.field_rules, - update: sinon.stub().resolves({ uid: 'updated-ct' }) + update: sinon.stub().resolves({ uid: 'updated-ct' }), }; mockStackClient.contentType.returns({ - fetch: sinon.stub().resolves(mockContentTypeResponse) + fetch: sinon.stub().resolves(mockContentTypeResponse), }); await entriesImport['updateFieldRules'](); @@ -542,7 +540,7 @@ describe('EntriesImport', () => { it('should handle content type not found', async () => { mockStackClient.contentType.returns({ - fetch: sinon.stub().resolves(null) + fetch: sinon.stub().resolves(null), }); await entriesImport['updateFieldRules'](); @@ -553,7 +551,7 @@ describe('EntriesImport', () => { it('should handle content type without field rules', async () => { const contentTypeWithoutFieldRules = { ...mockData.contentTypeWithFieldRules, - field_rules: undefined + field_rules: undefined, }; fsUtilityReadFileStub.callsFake((path) => { @@ -582,11 +580,11 @@ describe('EntriesImport', () => { mockData.contentTypeWithRte, mockData.contentTypeWithAssets, mockData.contentTypeWithTaxonomy, - mockData.contentTypeWithGroups + mockData.contentTypeWithGroups, ]; entriesImport['locales'] = [ { code: 'en-us', name: 'English (United States)' }, - { code: 'fr-fr', name: 'French (France)' } + { code: 'fr-fr', name: 'French (France)' }, ]; entriesImport['installedExtensions'] = mockMappers.installedExtensions; entriesImport['assetUidMapper'] = mockMappers.assetUidMapper; @@ -602,7 +600,7 @@ describe('EntriesImport', () => { expect(result).to.have.lengthOf(14); // 7 content types × 2 locales // Check that all content types are included - const contentTypes = result.map(option => option.cTUid); + const contentTypes = result.map((option) => option.cTUid); expect(contentTypes).to.include('simple_ct'); expect(contentTypes).to.include('ref_ct'); expect(contentTypes).to.include('json_rte_ct'); @@ -612,12 +610,12 @@ describe('EntriesImport', () => { expect(contentTypes).to.include('group_ct'); // Check that all locales are included - const locales = result.map(option => option.locale); + const locales = result.map((option) => option.locale); expect(locales).to.include('en-us'); expect(locales).to.include('fr-fr'); // Check structure of each option - result.forEach(option => { + result.forEach((option) => { expect(option).to.have.property('cTUid'); expect(option).to.have.property('locale'); expect(option.cTUid).to.be.a('string'); @@ -645,7 +643,7 @@ describe('EntriesImport', () => { describe('createEntries()', () => { it('should handle empty chunks', async () => { const mockFsUtility = { - indexFileContent: {} + indexFileContent: {}, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); @@ -657,16 +655,16 @@ describe('EntriesImport', () => { it('should process entries successfully in master locale', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1', 'entry2'] - } + 'chunk1.json': ['entry1', 'entry2'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.simpleEntry, - 'entry2': mockEntries.entryWithReferences - }) + entry1: mockEntries.simpleEntry, + entry2: mockEntries.entryWithReferences, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -686,8 +684,8 @@ describe('EntriesImport', () => { locale: 'en-us', cTUid: 'simple_ct', entryFileName: 'chunk1.json', - isMasterLocale: true - } + isMasterLocale: true, + }, }); }); @@ -700,30 +698,30 @@ describe('EntriesImport', () => { expect(mockReadChunkFiles.next.called).to.be.true; expect(mockWriteIntoFile.called).to.be.true; expect(mockCompleteFile.called).to.be.true; - + // Check that UID mapping was created expect(entriesImport['entriesUidMapper']['simple_entry_1']).to.equal('new_simple_entry_1'); - + // Check that entry was added to variant list expect(entriesImport['entriesForVariant']).to.deep.include({ content_type: 'simple_ct', entry_uid: 'simple_entry_1', - locale: 'en-us' + locale: 'en-us', }); }); it('should process entries successfully in non-master locale', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.simpleEntry - }) + entry1: mockEntries.simpleEntry, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -742,8 +740,8 @@ describe('EntriesImport', () => { locale: 'fr-fr', cTUid: 'simple_ct', entryFileName: 'chunk1.json', - isMasterLocale: false - } + isMasterLocale: false, + }, }); }); @@ -753,27 +751,27 @@ describe('EntriesImport', () => { await entriesImport['createEntries']({ cTUid: 'simple_ct', locale: 'fr-fr' }); expect(makeConcurrentCallStub.called).to.be.true; - + // Check that entry was added to auto-created entries for cleanup expect(entriesImport['autoCreatedEntries']).to.deep.include({ cTUid: 'simple_ct', locale: 'fr-fr', - entryUid: 'new_simple_entry_1' + entryUid: 'new_simple_entry_1', }); }); it('should handle localized entries correctly', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.localizedEntry - }) + entry1: mockEntries.localizedEntry, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -795,42 +793,42 @@ describe('EntriesImport', () => { isMasterLocale: false, [mockEntries.localizedEntry.uid]: { isLocalized: true, - entryOldUid: 'old_localized_entry_1' - } - } + entryOldUid: 'old_localized_entry_1', + }, + }, }); }); await entriesImport['createEntries']({ cTUid: 'simple_ct', locale: 'fr-fr' }); expect(makeConcurrentCallStub.called).to.be.true; - + // Check that localized entry was added to variant list with old UID expect(entriesImport['entriesForVariant']).to.deep.include({ content_type: 'simple_ct', entry_uid: 'old_localized_entry_1', - locale: 'fr-fr' + locale: 'fr-fr', }); }); it('should handle chunk read errors', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const originalCompleteFile = FsUtility.prototype.completeFile; FsUtility.prototype.completeFile = sinon.stub().resolves(); - + const mockReadChunkFiles = { - next: sinon.stub().rejects(new Error('Chunk read failed')) + next: sinon.stub().rejects(new Error('Chunk read failed')), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); try { - await entriesImport['createEntries']({ cTUid: 'simple_ct', locale: 'en-us' }); + await entriesImport['createEntries']({ cTUid: 'simple_ct', locale: 'en-us' }); } catch (error) { // Expected to throw error } finally { @@ -844,15 +842,15 @@ describe('EntriesImport', () => { it('should handle error code 119 with replaceExisting true', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.existingEntry - }) + entry1: mockEntries.existingEntry, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -864,9 +862,9 @@ describe('EntriesImport', () => { makeConcurrentCallStub.callsFake(async (options) => { const onReject = options.apiParams.reject; onReject({ - error: { - errorCode: 119, - errors: { title: 'already exists' } + error: { + errorCode: 119, + errors: { title: 'already exists' }, }, apiData: mockEntries.existingEntry, additionalInfo: { @@ -874,8 +872,8 @@ describe('EntriesImport', () => { locale: 'en-us', cTUid: 'simple_ct', entryFileName: 'chunk1.json', - isMasterLocale: true - } + isMasterLocale: true, + }, }); }); @@ -892,15 +890,15 @@ describe('EntriesImport', () => { it('should handle error code 119 with skipExisting true', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.existingEntry - }) + entry1: mockEntries.existingEntry, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -912,9 +910,9 @@ describe('EntriesImport', () => { makeConcurrentCallStub.callsFake(async (options) => { const onReject = options.apiParams.reject; onReject({ - error: { - errorCode: 119, - errors: { title: 'already exists' } + error: { + errorCode: 119, + errors: { title: 'already exists' }, }, apiData: mockEntries.existingEntry, additionalInfo: { @@ -922,8 +920,8 @@ describe('EntriesImport', () => { locale: 'en-us', cTUid: 'simple_ct', entryFileName: 'chunk1.json', - isMasterLocale: true - } + isMasterLocale: true, + }, }); }); @@ -938,15 +936,15 @@ describe('EntriesImport', () => { it('should handle error code 119 without title/uid errors', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.existingEntry - }) + entry1: mockEntries.existingEntry, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -958,9 +956,9 @@ describe('EntriesImport', () => { makeConcurrentCallStub.callsFake(async (options) => { const onReject = options.apiParams.reject; onReject({ - error: { - errorCode: 119, - errors: { other: 'some error' } + error: { + errorCode: 119, + errors: { other: 'some error' }, }, apiData: mockEntries.existingEntry, additionalInfo: { @@ -968,8 +966,8 @@ describe('EntriesImport', () => { locale: 'en-us', cTUid: 'simple_ct', entryFileName: 'chunk1.json', - isMasterLocale: true - } + isMasterLocale: true, + }, }); }); @@ -980,22 +978,22 @@ describe('EntriesImport', () => { expect(entriesImport['failedEntries']).to.deep.include({ content_type: 'simple_ct', locale: 'en-us', - entry: { uid: 'existing_entry_1', title: 'Existing Entry' } + entry: { uid: 'existing_entry_1', title: 'Existing Entry' }, }); }); it('should handle other error codes', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.simpleEntry - }) + entry1: mockEntries.simpleEntry, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -1007,9 +1005,9 @@ describe('EntriesImport', () => { makeConcurrentCallStub.callsFake(async (options) => { const onReject = options.apiParams.reject; onReject({ - error: { - errorCode: 500, - message: 'Server error' + error: { + errorCode: 500, + message: 'Server error', }, apiData: mockEntries.simpleEntry, additionalInfo: { @@ -1017,8 +1015,8 @@ describe('EntriesImport', () => { locale: 'en-us', cTUid: 'simple_ct', entryFileName: 'chunk1.json', - isMasterLocale: true - } + isMasterLocale: true, + }, }); }); @@ -1029,22 +1027,22 @@ describe('EntriesImport', () => { expect(entriesImport['failedEntries']).to.deep.include({ content_type: 'simple_ct', locale: 'en-us', - entry: { uid: 'simple_entry_1', title: 'Simple Entry 1' } + entry: { uid: 'simple_entry_1', title: 'Simple Entry 1' }, }); }); it('should remove failed entries from variant list', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.simpleEntry - }) + entry1: mockEntries.simpleEntry, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -1055,15 +1053,15 @@ describe('EntriesImport', () => { // Pre-populate variant list entriesImport['entriesForVariant'] = [ - { content_type: 'simple_ct', entry_uid: 'simple_entry_1', locale: 'en-us' } + { content_type: 'simple_ct', entry_uid: 'simple_entry_1', locale: 'en-us' }, ]; makeConcurrentCallStub.callsFake(async (options) => { const onReject = options.apiParams.reject; onReject({ - error: { - errorCode: 500, - message: 'Server error' + error: { + errorCode: 500, + message: 'Server error', }, apiData: mockEntries.simpleEntry, additionalInfo: { @@ -1071,8 +1069,8 @@ describe('EntriesImport', () => { locale: 'en-us', cTUid: 'simple_ct', entryFileName: 'chunk1.json', - isMasterLocale: true - } + isMasterLocale: true, + }, }); }); @@ -1082,7 +1080,7 @@ describe('EntriesImport', () => { expect(entriesImport['entriesForVariant']).to.not.deep.include({ content_type: 'simple_ct', entry_uid: 'simple_entry_1', - locale: 'en-us' + locale: 'en-us', }); }); @@ -1090,21 +1088,21 @@ describe('EntriesImport', () => { const mockFsUtility = { indexFileContent: { 'chunk1.json': ['entry1'], - 'chunk2.json': ['entry2'] - } + 'chunk2.json': ['entry2'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + let chunkCallCount = 0; const mockReadChunkFiles = { next: sinon.stub().callsFake(() => { chunkCallCount++; if (chunkCallCount === 1) { - return Promise.resolve({ 'entry1': mockEntries.simpleEntry }); + return Promise.resolve({ entry1: mockEntries.simpleEntry }); } else { - return Promise.resolve({ 'entry2': mockEntries.entryWithReferences }); + return Promise.resolve({ entry2: mockEntries.entryWithReferences }); } - }) + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -1123,8 +1121,8 @@ describe('EntriesImport', () => { locale: 'en-us', cTUid: 'simple_ct', entryFileName: 'chunk1.json', - isMasterLocale: true - } + isMasterLocale: true, + }, }); }); @@ -1146,8 +1144,8 @@ describe('EntriesImport', () => { cTUid: 'simple_ct', locale: 'en-us', contentType: mockData.simpleContentType, - isMasterLocale: true - } + isMasterLocale: true, + }, }; const result = entriesImport['serializeEntries'](apiOptions); @@ -1167,8 +1165,8 @@ describe('EntriesImport', () => { cTUid: 'json_rte_ct', locale: 'en-us', contentType: mockData.contentTypeWithJsonRte, - isMasterLocale: true - } + isMasterLocale: true, + }, }; entriesImport['jsonRteCTs'] = ['json_rte_ct']; @@ -1190,8 +1188,8 @@ describe('EntriesImport', () => { cTUid: 'rte_ct', locale: 'en-us', contentType: mockData.contentTypeWithRte, - isMasterLocale: true - } + isMasterLocale: true, + }, }; entriesImport['rteCTsWithRef'] = ['rte_ct']; @@ -1212,8 +1210,8 @@ describe('EntriesImport', () => { cTUid: 'taxonomy_ct', locale: 'en-us', contentType: mockData.contentTypeWithTaxonomy, - isMasterLocale: true - } + isMasterLocale: true, + }, }; const result = entriesImport['serializeEntries'](apiOptions); @@ -1232,11 +1230,11 @@ describe('EntriesImport', () => { cTUid: 'simple_ct', locale: 'fr-fr', contentType: mockData.simpleContentType, - isMasterLocale: false - } + isMasterLocale: false, + }, }; - entriesImport['entriesUidMapper'] = { 'old_localized_entry_1': 'new_localized_entry_1' }; + entriesImport['entriesUidMapper'] = { old_localized_entry_1: 'new_localized_entry_1' }; const originalLookupAssets = require('../../../../src/utils').lookupAssets; Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { @@ -1247,17 +1245,17 @@ describe('EntriesImport', () => { // Return the modified entry return entryData.entry; }, - configurable: true + configurable: true, }); const mockEntryResponse = { uid: 'new_localized_entry_1' }; const mockEntry = { - uid: sinon.stub().returns(mockEntryResponse) + uid: sinon.stub().returns(mockEntryResponse), }; mockStackClient.contentType = sinon.stub().returns({ - entry: sinon.stub().returns(mockEntry) + entry: sinon.stub().returns(mockEntry), }); - + sinon.stub(entriesImport, 'stack').value(mockStackClient); const result = entriesImport['serializeEntries'](apiOptions); @@ -1266,12 +1264,12 @@ describe('EntriesImport', () => { expect(result.apiData.uid).to.equal('new_localized_entry_1'); // UID is mapped for localized entries expect(result.additionalInfo['new_localized_entry_1']).to.deep.include({ isLocalized: true, - entryOldUid: 'old_localized_entry_1' + entryOldUid: 'old_localized_entry_1', }); Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { value: originalLookupAssets, - configurable: true + configurable: true, }); }); @@ -1285,30 +1283,30 @@ describe('EntriesImport', () => { cTUid: 'simple_ct', locale: 'en-us', contentType: mockData.simpleContentType, - isMasterLocale: true - } + isMasterLocale: true, + }, }; const invalidEntry = { uid: 'invalid_entry', title: 'Invalid Entry', // This will cause an error in lookupAssets due to missing required properties - invalid_field: 'test' + invalid_field: 'test', }; const invalidApiOptions = { ...apiOptions, - apiData: invalidEntry + apiData: invalidEntry, }; const lookupAssetsStub = sinon.stub().throws(new Error('Asset lookup failed')); const utils = require('../../../../src/utils'); - + // Use Object.defineProperty to override the getter Object.defineProperty(utils, 'lookupAssets', { value: lookupAssetsStub, writable: true, - configurable: true + configurable: true, }); const result = entriesImport['serializeEntries'](invalidApiOptions); @@ -1319,7 +1317,7 @@ describe('EntriesImport', () => { expect(entriesImport['failedEntries'][0]).to.deep.include({ content_type: 'simple_ct', locale: 'en-us', - entry: { uid: 'invalid_entry', title: 'Invalid Entry' } + entry: { uid: 'invalid_entry', title: 'Invalid Entry' }, }); }); }); @@ -1328,7 +1326,7 @@ describe('EntriesImport', () => { it('should create variant entry data file', () => { entriesImport['entriesForVariant'] = [ { content_type: 'simple_ct', entry_uid: 'entry_1', locale: 'fr-fr' }, - { content_type: 'ref_ct', entry_uid: 'entry_2', locale: 'en-us' } + { content_type: 'ref_ct', entry_uid: 'entry_2', locale: 'en-us' }, ]; const originalWriteFileSync = require('fs').writeFileSync; @@ -1368,11 +1366,11 @@ describe('EntriesImport', () => { mockData.simpleContentType, mockData.contentTypeWithReferences, mockData.contentTypeWithJsonRte, - mockData.contentTypeWithRte + mockData.contentTypeWithRte, ]; entriesImport['locales'] = [ { code: 'en-us', name: 'English (United States)' }, - { code: 'fr-fr', name: 'French (France)' } + { code: 'fr-fr', name: 'French (France)' }, ]; entriesImport['refCTs'] = ['ref_ct', 'json_rte_ct', 'rte_ct']; entriesImport['jsonRteCTs'] = ['json_rte_ct']; @@ -1382,10 +1380,10 @@ describe('EntriesImport', () => { entriesImport['assetUrlMapper'] = mockMappers.assetUrlMapper; entriesImport['taxonomies'] = mockMappers.taxonomies; entriesImport['entriesUidMapper'] = { - 'simple_entry_1': 'new_simple_entry_1', - 'ref_entry_1': 'new_ref_entry_1', - 'json_rte_entry_1': 'new_json_rte_entry_1', - 'rte_entry_1': 'new_rte_entry_1' + simple_entry_1: 'new_simple_entry_1', + ref_entry_1: 'new_ref_entry_1', + json_rte_entry_1: 'new_json_rte_entry_1', + rte_entry_1: 'new_rte_entry_1', }; }); @@ -1397,13 +1395,13 @@ describe('EntriesImport', () => { expect(result).to.have.lengthOf(6); // 3 ref content types × 2 locales // Check that all reference content types are included - const contentTypes = result.map(option => option.cTUid); + const contentTypes = result.map((option) => option.cTUid); expect(contentTypes).to.include('ref_ct'); expect(contentTypes).to.include('json_rte_ct'); expect(contentTypes).to.include('rte_ct'); // Check that all locales are included - const locales = result.map(option => option.locale); + const locales = result.map((option) => option.locale); expect(locales).to.include('en-us'); expect(locales).to.include('fr-fr'); }); @@ -1428,7 +1426,7 @@ describe('EntriesImport', () => { describe('updateEntriesWithReferences()', () => { it('should handle empty chunks', async () => { const mockFsUtility = { - indexFileContent: {} + indexFileContent: {}, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); @@ -1440,16 +1438,16 @@ describe('EntriesImport', () => { it('should process entries with references successfully', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1', 'entry2'] - } + 'chunk1.json': ['entry1', 'entry2'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.entryWithReferences, - 'entry2': mockEntries.simpleEntry - }) + entry1: mockEntries.entryWithReferences, + entry2: mockEntries.simpleEntry, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -1457,7 +1455,7 @@ describe('EntriesImport', () => { const onSuccess = options.apiParams.resolve; onSuccess({ response: { uid: 'updated-entry-uid' }, - apiData: { uid: 'ref_entry_1', url: '/ref-entry-1', title: 'Entry with References' } + apiData: { uid: 'ref_entry_1', url: '/ref-entry-1', title: 'Entry with References' }, }); }); @@ -1470,13 +1468,13 @@ describe('EntriesImport', () => { it('should handle chunk read errors', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { - next: sinon.stub().rejects(new Error('Chunk read failed')) + next: sinon.stub().rejects(new Error('Chunk read failed')), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -1489,15 +1487,15 @@ describe('EntriesImport', () => { it('should handle API errors in onReject', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.entryWithReferences - }) + entry1: mockEntries.entryWithReferences, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -1505,7 +1503,7 @@ describe('EntriesImport', () => { const onReject = options.apiParams.reject; onReject({ error: { status: 500, message: 'Update failed' }, - apiData: { uid: 'ref_entry_1', title: 'Entry with References' } + apiData: { uid: 'ref_entry_1', title: 'Entry with References' }, }); }); @@ -1516,7 +1514,7 @@ describe('EntriesImport', () => { content_type: 'ref_ct', locale: 'en-us', entry: { uid: 'new_ref_entry_1', title: 'Entry with References' }, - entryId: 'ref_entry_1' + entryId: 'ref_entry_1', }); }); }); @@ -1528,7 +1526,7 @@ describe('EntriesImport', () => { uid: 'ref_entry_1', title: 'Entry with References', sourceEntryFilePath: '/path/to/source.json', - entryOldUid: 'ref_entry_1' + entryOldUid: 'ref_entry_1', }, entity: 'update-entries' as const, resolve: sinon.stub(), @@ -1536,21 +1534,21 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'ref_ct', locale: 'en-us', - contentType: mockData.contentTypeWithReferences - } + contentType: mockData.contentTypeWithReferences, + }, }; fsUtilityReadFileStub.callsFake((path) => { if (path.includes('source.json')) { return { - 'ref_entry_1': { + ref_entry_1: { uid: 'ref_entry_1', title: 'Source Entry', single_reference: { uid: 'simple_entry_1', - _content_type_uid: 'simple_ct' - } - } + _content_type_uid: 'simple_ct', + }, + }, }; } return {}; @@ -1559,7 +1557,7 @@ describe('EntriesImport', () => { const originalLookupAssets = require('../../../../src/utils').lookupAssets; Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { get: () => (entryData: any) => entryData.entry, - configurable: true + configurable: true, }); const result = entriesImport['serializeUpdateEntries'](apiOptions); @@ -1570,7 +1568,7 @@ describe('EntriesImport', () => { Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { get: () => originalLookupAssets, - configurable: true + configurable: true, }); }); @@ -1580,7 +1578,7 @@ describe('EntriesImport', () => { uid: 'json_rte_entry_1', title: 'Entry with JSON RTE', sourceEntryFilePath: '/path/to/source.json', - entryOldUid: 'json_rte_entry_1' + entryOldUid: 'json_rte_entry_1', }, entity: 'update-entries' as const, resolve: sinon.stub(), @@ -1588,14 +1586,14 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'json_rte_ct', locale: 'en-us', - contentType: mockData.contentTypeWithJsonRte - } + contentType: mockData.contentTypeWithJsonRte, + }, }; fsUtilityReadFileStub.callsFake((path) => { if (path.includes('source.json')) { return { - 'json_rte_entry_1': { + json_rte_entry_1: { uid: 'json_rte_entry_1', title: 'Source Entry', json_rte_field: { @@ -1608,14 +1606,14 @@ describe('EntriesImport', () => { type: 'reference', attrs: { type: 'entry', - 'entry-uid': 'simple_entry_1' - } - } - ] - } - ] - } - } + 'entry-uid': 'simple_entry_1', + }, + }, + ], + }, + ], + }, + }, }; } return {}; @@ -1624,7 +1622,7 @@ describe('EntriesImport', () => { const originalLookupAssets = require('../../../../src/utils').lookupAssets; Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { get: () => (entryData: any) => entryData.entry, - configurable: true + configurable: true, }); const result = entriesImport['serializeUpdateEntries'](apiOptions); @@ -1634,7 +1632,7 @@ describe('EntriesImport', () => { Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { get: () => originalLookupAssets, - configurable: true + configurable: true, }); }); @@ -1644,7 +1642,7 @@ describe('EntriesImport', () => { uid: 'rte_entry_1', title: 'Entry with RTE', sourceEntryFilePath: '/path/to/source.json', - entryOldUid: 'rte_entry_1' + entryOldUid: 'rte_entry_1', }, entity: 'update-entries' as const, resolve: sinon.stub(), @@ -1652,18 +1650,18 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'rte_ct', locale: 'en-us', - contentType: mockData.contentTypeWithRte - } + contentType: mockData.contentTypeWithRte, + }, }; fsUtilityReadFileStub.callsFake((path) => { if (path.includes('source.json')) { return { - 'rte_entry_1': { + rte_entry_1: { uid: 'rte_entry_1', title: 'Source Entry', - rte_field: '

RTE content with entry link

' - } + rte_field: '

RTE content with entry link

', + }, }; } return {}; @@ -1672,7 +1670,7 @@ describe('EntriesImport', () => { const originalLookupAssets = require('../../../../src/utils').lookupAssets; Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { get: () => (entryData: any) => entryData.entry, - configurable: true + configurable: true, }); const result = entriesImport['serializeUpdateEntries'](apiOptions); @@ -1682,7 +1680,7 @@ describe('EntriesImport', () => { Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { get: () => originalLookupAssets, - configurable: true + configurable: true, }); }); @@ -1692,7 +1690,7 @@ describe('EntriesImport', () => { uid: 'invalid_entry', title: 'Invalid Entry', sourceEntryFilePath: '/path/to/source.json', - entryOldUid: 'invalid_entry' + entryOldUid: 'invalid_entry', }, entity: 'update-entries' as const, resolve: sinon.stub(), @@ -1700,8 +1698,8 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'ref_ct', locale: 'en-us', - contentType: mockData.contentTypeWithReferences - } + contentType: mockData.contentTypeWithReferences, + }, }; fsUtilityReadFileStub.callsFake(() => { @@ -1717,7 +1715,7 @@ describe('EntriesImport', () => { describe('replaceEntries()', () => { it('should handle empty chunks', async () => { const mockFsUtility = { - indexFileContent: {} + indexFileContent: {}, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); @@ -1729,22 +1727,22 @@ describe('EntriesImport', () => { it('should process existing entries for replacement', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.existingEntry - }) + entry1: mockEntries.existingEntry, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); sinon.stub(FsUtility.prototype, 'writeIntoFile').callsFake(() => { return Promise.resolve(); }); - + const originalWriteFileSync = require('fs').writeFileSync; const writeFileSyncStub = sinon.stub(require('fs'), 'writeFileSync').callsFake(() => {}); @@ -1753,7 +1751,7 @@ describe('EntriesImport', () => { onSuccess({ response: { uid: 'replaced-entry-uid' }, apiData: mockEntries.existingEntry, - additionalInfo: {} + additionalInfo: {}, }); }); @@ -1766,13 +1764,13 @@ describe('EntriesImport', () => { it('should handle chunk read errors', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { - next: sinon.stub().rejects(new Error('Chunk read failed')) + next: sinon.stub().rejects(new Error('Chunk read failed')), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -1785,15 +1783,15 @@ describe('EntriesImport', () => { it('should handle API errors in onReject', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.existingEntry - }) + entry1: mockEntries.existingEntry, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -1803,7 +1801,7 @@ describe('EntriesImport', () => { const onReject = options.apiParams.reject; onReject({ error: { status: 500, message: 'Replacement failed' }, - apiData: { uid: 'existing_entry_1', title: 'Existing Entry' } + apiData: { uid: 'existing_entry_1', title: 'Existing Entry' }, }); }); @@ -1814,7 +1812,7 @@ describe('EntriesImport', () => { content_type: 'ref_ct', locale: 'en-us', entry: { uid: undefined, title: 'Existing Entry' }, - entryId: 'existing_entry_1' + entryId: 'existing_entry_1', }); }); }); @@ -1823,7 +1821,7 @@ describe('EntriesImport', () => { it('should find and update existing entry', async () => { const mockEntry = { title: 'Existing Entry', - uid: 'existing_entry_1' + uid: 'existing_entry_1', }; const apiParams = { @@ -1832,58 +1830,62 @@ describe('EntriesImport', () => { reject: sinon.stub(), additionalInfo: { cTUid: 'ref_ct', - locale: 'en-us' - } + locale: 'en-us', + }, }; const mockQuery = { findOne: sinon.stub().resolves({ - items: [{ - uid: 'stack_entry_uid', - title: 'Existing Entry', - urlPath: '/existing-entry', - stackHeaders: {}, - _version: 1 - }] - }) + items: [ + { + uid: 'stack_entry_uid', + title: 'Existing Entry', + urlPath: '/existing-entry', + stackHeaders: {}, + _version: 1, + }, + ], + }), }; const mockEntryPayload = { - update: sinon.stub().resolves({ uid: 'updated_entry_uid' }) + update: sinon.stub().resolves({ uid: 'updated_entry_uid' }), }; const mockQueryChain = { query: sinon.stub().returns({ findOne: sinon.stub().resolves({ - items: [{ - uid: 'stack_entry_uid', - title: 'Existing Entry', - urlPath: '/existing-entry', - stackHeaders: {}, - _version: 1 - }] - }) - }) + items: [ + { + uid: 'stack_entry_uid', + title: 'Existing Entry', + urlPath: '/existing-entry', + stackHeaders: {}, + _version: 1, + }, + ], + }), + }), }; const mockEntryChain = { - update: sinon.stub().resolves({ uid: 'updated_entry_uid' }) + update: sinon.stub().resolves({ uid: 'updated_entry_uid' }), }; const contentTypeStub = sinon.stub(); contentTypeStub.onFirstCall().returns({ - entry: sinon.stub().returns(mockQueryChain) + entry: sinon.stub().returns(mockQueryChain), }); contentTypeStub.onSecondCall().returns({ - entry: sinon.stub().returns(mockEntryChain) + entry: sinon.stub().returns(mockEntryChain), }); - + mockStackClient.contentType = contentTypeStub; const result = await entriesImport['replaceEntriesHandler']({ apiParams, element: mockEntry, - isLastRequest: false + isLastRequest: false, }); expect(result).to.be.true; @@ -1895,7 +1897,7 @@ describe('EntriesImport', () => { it('should handle entry not found in stack', async () => { const mockEntry = { title: 'Non-existent Entry', - uid: 'non_existent_entry_1' + uid: 'non_existent_entry_1', }; const apiParams = { @@ -1904,30 +1906,30 @@ describe('EntriesImport', () => { reject: sinon.stub(), additionalInfo: { cTUid: 'ref_ct', - locale: 'en-us' - } + locale: 'en-us', + }, }; const mockQueryChain = { query: sinon.stub().returns({ findOne: sinon.stub().resolves({ - items: [] - }) - }) + items: [], + }), + }), }; const contentTypeStub = sinon.stub(); contentTypeStub.returns({ - entry: sinon.stub().returns(mockQueryChain) + entry: sinon.stub().returns(mockQueryChain), }); - + mockStackClient.contentType = contentTypeStub; try { const result = await entriesImport['replaceEntriesHandler']({ apiParams, element: mockEntry, - isLastRequest: false + isLastRequest: false, }); expect.fail('Expected method to reject'); } catch (error) { @@ -1940,7 +1942,7 @@ describe('EntriesImport', () => { it('should handle query errors', async () => { const mockEntry = { title: 'Error Entry', - uid: 'error_entry_1' + uid: 'error_entry_1', }; const apiParams = { @@ -1949,28 +1951,28 @@ describe('EntriesImport', () => { reject: sinon.stub(), additionalInfo: { cTUid: 'ref_ct', - locale: 'en-us' - } + locale: 'en-us', + }, }; const mockQueryChain = { query: sinon.stub().returns({ - findOne: sinon.stub().rejects(new Error('Query failed')) - }) + findOne: sinon.stub().rejects(new Error('Query failed')), + }), }; const contentTypeStub = sinon.stub(); contentTypeStub.returns({ - entry: sinon.stub().returns(mockQueryChain) + entry: sinon.stub().returns(mockQueryChain), }); - + mockStackClient.contentType = contentTypeStub; try { const result = await entriesImport['replaceEntriesHandler']({ apiParams, element: mockEntry, - isLastRequest: false + isLastRequest: false, }); expect.fail('Expected method to reject'); } catch (error) { @@ -1982,7 +1984,7 @@ describe('EntriesImport', () => { it('should handle update errors', async () => { const mockEntry = { title: 'Update Error Entry', - uid: 'update_error_entry_1' + uid: 'update_error_entry_1', }; const apiParams = { @@ -1991,43 +1993,45 @@ describe('EntriesImport', () => { reject: sinon.stub(), additionalInfo: { cTUid: 'ref_ct', - locale: 'en-us' - } + locale: 'en-us', + }, }; const mockQueryChain = { query: sinon.stub().returns({ findOne: sinon.stub().resolves({ - items: [{ - uid: 'stack_entry_uid', - title: 'Update Error Entry', - urlPath: '/update-error-entry', - stackHeaders: {}, - _version: 1 - }] - }) - }) + items: [ + { + uid: 'stack_entry_uid', + title: 'Update Error Entry', + urlPath: '/update-error-entry', + stackHeaders: {}, + _version: 1, + }, + ], + }), + }), }; const mockEntryChain = { - update: sinon.stub().rejects(new Error('Update failed')) + update: sinon.stub().rejects(new Error('Update failed')), }; const contentTypeStub = sinon.stub(); contentTypeStub.onFirstCall().returns({ - entry: sinon.stub().returns(mockQueryChain) + entry: sinon.stub().returns(mockQueryChain), }); contentTypeStub.onSecondCall().returns({ - entry: sinon.stub().returns(mockEntryChain) + entry: sinon.stub().returns(mockEntryChain), }); - + mockStackClient.contentType = contentTypeStub; try { const result = await entriesImport['replaceEntriesHandler']({ apiParams, element: mockEntry, - isLastRequest: false + isLastRequest: false, }); expect.fail('Expected method to reject'); } catch (error) { @@ -2043,23 +2047,23 @@ describe('EntriesImport', () => { entriesImport['cTs'] = [ mockData.simpleContentType, mockData.contentTypeWithReferences, - mockData.contentTypeWithJsonRte + mockData.contentTypeWithJsonRte, ]; entriesImport['envs'] = { - 'env_1': { name: 'production', uid: 'env_1' }, - 'env_2': { name: 'staging', uid: 'env_2' } + env_1: { name: 'production', uid: 'env_1' }, + env_2: { name: 'staging', uid: 'env_2' }, }; entriesImport['entriesUidMapper'] = { - 'simple_entry_1': 'new_simple_entry_1', - 'publish_entry_1': 'new_publish_entry_1', - 'json_rte_entry_1': 'new_json_rte_entry_1' + simple_entry_1: 'new_simple_entry_1', + publish_entry_1: 'new_publish_entry_1', + json_rte_entry_1: 'new_json_rte_entry_1', }; }); describe('publishEntries()', () => { it('should handle empty chunks', async () => { const mockFsUtility = { - indexFileContent: {} + indexFileContent: {}, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); @@ -2071,16 +2075,16 @@ describe('EntriesImport', () => { it('should process entries with publish details successfully', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1', 'entry2'] - } + 'chunk1.json': ['entry1', 'entry2'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.simpleEntry, - 'entry2': mockEntries.entryWithPublishDetails - }) + entry1: mockEntries.simpleEntry, + entry2: mockEntries.entryWithPublishDetails, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -2088,11 +2092,11 @@ describe('EntriesImport', () => { const onSuccess = options.apiParams.resolve; onSuccess({ response: { uid: 'published-entry-uid' }, - apiData: { - environments: ['production', 'staging'], - entryUid: 'new_simple_entry_1', - locales: ['en-us'] - } + apiData: { + environments: ['production', 'staging'], + entryUid: 'new_simple_entry_1', + locales: ['en-us'], + }, }); }); @@ -2105,15 +2109,15 @@ describe('EntriesImport', () => { it('should handle entries with multiple publish details', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.entryWithPublishDetails - }) + entry1: mockEntries.entryWithPublishDetails, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -2121,11 +2125,11 @@ describe('EntriesImport', () => { const onSuccess = options.apiParams.resolve; onSuccess({ response: { uid: 'published-entry-uid' }, - apiData: { - environments: ['production', 'staging'], - entryUid: 'new_publish_entry_1', - locales: ['en-us', 'fr-fr'] - } + apiData: { + environments: ['production', 'staging'], + entryUid: 'new_publish_entry_1', + locales: ['en-us', 'fr-fr'], + }, }); }); @@ -2139,22 +2143,22 @@ describe('EntriesImport', () => { it('should handle entries without publish details', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const entryWithoutPublishDetails = { uid: 'no_publish_entry_1', title: 'Entry without Publish Details', - description: 'This entry has no publish details' + description: 'This entry has no publish details', // No publish_details property }; - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': entryWithoutPublishDetails - }) + entry1: entryWithoutPublishDetails, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -2167,22 +2171,22 @@ describe('EntriesImport', () => { it('should handle entries with empty publish details', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const entryWithEmptyPublishDetails = { uid: 'empty_publish_entry_1', title: 'Entry with Empty Publish Details', description: 'This entry has empty publish details', - publish_details: [] as any[] + publish_details: [] as any[], }; - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': entryWithEmptyPublishDetails - }) + entry1: entryWithEmptyPublishDetails, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -2195,13 +2199,13 @@ describe('EntriesImport', () => { it('should handle chunk read errors', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { - next: sinon.stub().rejects(new Error('Chunk read failed')) + next: sinon.stub().rejects(new Error('Chunk read failed')), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -2214,15 +2218,15 @@ describe('EntriesImport', () => { it('should handle API errors in onReject', async () => { const mockFsUtility = { indexFileContent: { - 'chunk1.json': ['entry1'] - } + 'chunk1.json': ['entry1'], + }, }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockFsUtility.indexFileContent); - + const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': mockEntries.simpleEntry - }) + entry1: mockEntries.simpleEntry, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -2230,11 +2234,11 @@ describe('EntriesImport', () => { const onReject = options.apiParams.reject; onReject({ error: { status: 500, message: 'Publish failed' }, - apiData: { - environments: ['production'], - entryUid: 'new_simple_entry_1', - locales: ['en-us'] - } + apiData: { + environments: ['production'], + entryUid: 'new_simple_entry_1', + locales: ['en-us'], + }, }); }); @@ -2253,13 +2257,13 @@ describe('EntriesImport', () => { publish_details: [ { environment: 'env_1', - locale: 'en-us' + locale: 'en-us', }, { environment: 'env_2', - locale: 'fr-fr' - } - ] + locale: 'fr-fr', + }, + ], }, entity: 'publish-entries' as const, resolve: sinon.stub(), @@ -2267,8 +2271,8 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'simple_ct', locale: 'en-us', - contentType: mockData.simpleContentType - } + contentType: mockData.simpleContentType, + }, }; const result = entriesImport['serializePublishEntries'](apiOptions); @@ -2277,7 +2281,7 @@ describe('EntriesImport', () => { expect(result.apiData).to.deep.include({ environments: ['production', 'staging'], locales: ['en-us', 'fr-fr'], - entryUid: 'new_simple_entry_1' + entryUid: 'new_simple_entry_1', }); }); @@ -2285,7 +2289,7 @@ describe('EntriesImport', () => { const apiOptions = { apiData: { uid: 'simple_entry_1', - title: 'Simple Entry' + title: 'Simple Entry', // No publish_details }, entity: 'publish-entries' as const, @@ -2294,8 +2298,8 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'simple_ct', locale: 'en-us', - contentType: mockData.simpleContentType - } + contentType: mockData.simpleContentType, + }, }; const result = entriesImport['serializePublishEntries'](apiOptions); @@ -2308,7 +2312,7 @@ describe('EntriesImport', () => { apiData: { uid: 'simple_entry_1', title: 'Simple Entry', - publish_details: [] as any[] + publish_details: [] as any[], }, entity: 'publish-entries' as const, resolve: sinon.stub(), @@ -2316,8 +2320,8 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'simple_ct', locale: 'en-us', - contentType: mockData.simpleContentType - } + contentType: mockData.simpleContentType, + }, }; const result = entriesImport['serializePublishEntries'](apiOptions); @@ -2333,9 +2337,9 @@ describe('EntriesImport', () => { publish_details: [ { environment: 'invalid_env', - locale: 'en-us' - } - ] + locale: 'en-us', + }, + ], }, entity: 'publish-entries' as const, resolve: sinon.stub(), @@ -2343,8 +2347,8 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'simple_ct', locale: 'en-us', - contentType: mockData.simpleContentType - } + contentType: mockData.simpleContentType, + }, }; const result = entriesImport['serializePublishEntries'](apiOptions); @@ -2359,10 +2363,10 @@ describe('EntriesImport', () => { title: 'Simple Entry', publish_details: [ { - environment: 'env_1' + environment: 'env_1', // No locale - } - ] + }, + ], }, entity: 'publish-entries' as const, resolve: sinon.stub(), @@ -2370,8 +2374,8 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'simple_ct', locale: 'en-us', - contentType: mockData.simpleContentType - } + contentType: mockData.simpleContentType, + }, }; const result = entriesImport['serializePublishEntries'](apiOptions); @@ -2387,17 +2391,17 @@ describe('EntriesImport', () => { publish_details: [ { environment: 'env_1', - locale: 'en-us' + locale: 'en-us', }, { environment: 'env_1', // Duplicate environment - locale: 'en-us' // Duplicate locale + locale: 'en-us', // Duplicate locale }, { environment: 'env_2', - locale: 'fr-fr' - } - ] + locale: 'fr-fr', + }, + ], }, entity: 'publish-entries' as const, resolve: sinon.stub(), @@ -2405,8 +2409,8 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'simple_ct', locale: 'en-us', - contentType: mockData.simpleContentType - } + contentType: mockData.simpleContentType, + }, }; const result = entriesImport['serializePublishEntries'](apiOptions); @@ -2426,9 +2430,9 @@ describe('EntriesImport', () => { publish_details: [ { environment: 'env_1', - locale: 'en-us' - } - ] + locale: 'en-us', + }, + ], }, entity: 'publish-entries' as const, resolve: sinon.stub(), @@ -2436,8 +2440,8 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'simple_ct', locale: 'en-us', - contentType: mockData.simpleContentType - } + contentType: mockData.simpleContentType, + }, }; const result = entriesImport['serializePublishEntries'](apiOptions); @@ -2454,17 +2458,17 @@ describe('EntriesImport', () => { publish_details: [ { environment: 'env_1', - locale: 'en-us' + locale: 'en-us', }, { environment: 'invalid_env', - locale: 'fr-fr' + locale: 'fr-fr', }, { environment: 'env_2', - locale: 'de-de' - } - ] + locale: 'de-de', + }, + ], }, entity: 'publish-entries' as const, resolve: sinon.stub(), @@ -2472,8 +2476,8 @@ describe('EntriesImport', () => { additionalInfo: { cTUid: 'simple_ct', locale: 'en-us', - contentType: mockData.simpleContentType - } + contentType: mockData.simpleContentType, + }, }; const result = entriesImport['serializePublishEntries'](apiOptions); @@ -2489,35 +2493,37 @@ describe('EntriesImport', () => { beforeEach(() => { // Reset all stubs before each test sinon.restore(); - + sinon.stub(FsUtility.prototype, 'createFolderIfNotExist').callsFake(() => { return Promise.resolve(); }); - + // Recreate entriesImport instance after restore entriesImport = new EntriesImport({ importConfig: mockImportConfig as any, stackAPIClient: mockStackClient, - moduleName: 'entries' + moduleName: 'entries', }); - + entriesImport['cTs'] = [mockData.simpleContentType, mockData.contentTypeWithReferences]; entriesImport['locales'] = [ { code: 'en-us', name: 'English' }, - { code: 'fr-fr', name: 'French' } + { code: 'fr-fr', name: 'French' }, ]; entriesImport['envs'] = { - 'env_1': { name: 'production', uid: 'env_1' }, - 'env_2': { name: 'staging', uid: 'env_2' } + env_1: { name: 'production', uid: 'env_1' }, + env_2: { name: 'staging', uid: 'env_2' }, }; entriesImport['entriesUidMapper'] = {}; entriesImport['failedEntries'] = []; entriesImport['autoCreatedEntries'] = []; entriesImport['entriesForVariant'] = []; - - sinon.stub(entriesImport as any, 'withLoadingSpinner').callsFake(async (message: string, action: () => Promise) => { - return await action(); - }); + + sinon + .stub(entriesImport as any, 'withLoadingSpinner') + .callsFake(async (message: string, action: () => Promise) => { + return await action(); + }); }); it('should complete full start process successfully', async () => { @@ -2526,13 +2532,13 @@ describe('EntriesImport', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(entriesImport as any, 'analyzeEntryData').resolves([2, 2, 2, 10, 5]); // contentTypesCount, localesCount, totalEntryChunks, totalActualEntries, totalEntriesForPublishing sinon.stub(entriesImport as any, 'createNestedProgress').returns(mockProgress); sinon.stub(entriesImport as any, 'initializeProgress').callsFake(() => {}); // Not async sinon.stub(entriesImport as any, 'completeProgress').callsFake(() => {}); - + const disableMandatoryCTReferencesStub = sinon.stub(entriesImport, 'disableMandatoryCTReferences').resolves(); sinon.stub(entriesImport as any, 'processEntryCreation').resolves(); sinon.stub(entriesImport as any, 'processEntryReplacement').resolves(); @@ -2581,7 +2587,7 @@ describe('EntriesImport', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(entriesImport as any, 'analyzeEntryData').resolves([2, 2, 2, 10, 5]); sinon.stub(entriesImport as any, 'createNestedProgress').returns(mockProgress); @@ -2589,15 +2595,22 @@ describe('EntriesImport', () => { sinon.stub(entriesImport as any, 'completeProgress').callsFake(() => {}); const mockFsUtil = { - readFile: sinon.stub() - .onCall(0).resolves([mockData.simpleContentType]) - .onCall(1).resolves({ extension_uid: {} }) - .onCall(2).resolves({}) - .onCall(3).resolves({}) - .onCall(4).resolves({}) - .onCall(5).resolves([{ code: 'en-us' }]), + readFile: sinon + .stub() + .onCall(0) + .resolves([mockData.simpleContentType]) + .onCall(1) + .resolves({ extension_uid: {} }) + .onCall(2) + .resolves({}) + .onCall(3) + .resolves({}) + .onCall(4) + .resolves({}) + .onCall(5) + .resolves([{ code: 'en-us' }]), makeDirectory: sinon.stub().resolves(), - writeFile: sinon.stub().resolves() + writeFile: sinon.stub().resolves(), }; sinon.stub(require('../../../../src/utils'), 'fsUtil').value(mockFsUtil); @@ -2606,7 +2619,7 @@ describe('EntriesImport', () => { const mockFileHelper = { readFileSync: sinon.stub().returns({}), - writeLargeFile: sinon.stub().resolves() + writeLargeFile: sinon.stub().resolves(), }; sinon.stub(require('../../../../src/utils'), 'fileHelper').value(mockFileHelper); @@ -2627,16 +2640,14 @@ describe('EntriesImport', () => { it('should handle autoCreatedEntries cleanup', async () => { // Set up autoCreatedEntries - entriesImport['autoCreatedEntries'] = [ - { cTUid: 'simple_ct', locale: 'en-us', entryUid: 'entry_1' } - ]; + entriesImport['autoCreatedEntries'] = [{ cTUid: 'simple_ct', locale: 'en-us', entryUid: 'entry_1' }]; const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(entriesImport as any, 'analyzeEntryData').resolves([2, 2, 2, 10, 5]); sinon.stub(entriesImport as any, 'createNestedProgress').returns(mockProgress); @@ -2667,7 +2678,7 @@ describe('EntriesImport', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(entriesImport as any, 'analyzeEntryData').resolves([2, 2, 2, 10, 5]); sinon.stub(entriesImport as any, 'createNestedProgress').returns(mockProgress); @@ -2698,7 +2709,7 @@ describe('EntriesImport', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(entriesImport as any, 'analyzeEntryData').resolves([2, 2, 2, 10, 5]); sinon.stub(entriesImport as any, 'createNestedProgress').returns(mockProgress); @@ -2729,7 +2740,7 @@ describe('EntriesImport', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(entriesImport as any, 'analyzeEntryData').resolves([2, 2, 2, 10, 5]); sinon.stub(entriesImport as any, 'createNestedProgress').returns(mockProgress); @@ -2755,16 +2766,14 @@ describe('EntriesImport', () => { it('should handle errors in removeAutoCreatedEntries', async () => { // Set up autoCreatedEntries - entriesImport['autoCreatedEntries'] = [ - { cTUid: 'simple_ct', locale: 'en-us', entryUid: 'entry_1' } - ]; + entriesImport['autoCreatedEntries'] = [{ cTUid: 'simple_ct', locale: 'en-us', entryUid: 'entry_1' }]; const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(entriesImport as any, 'analyzeEntryData').resolves([2, 2, 2, 10, 5]); sinon.stub(entriesImport as any, 'createNestedProgress').returns(mockProgress); @@ -2794,7 +2803,7 @@ describe('EntriesImport', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(entriesImport as any, 'analyzeEntryData').resolves([2, 2, 2, 10, 5]); sinon.stub(entriesImport as any, 'createNestedProgress').returns(mockProgress); @@ -2824,7 +2833,7 @@ describe('EntriesImport', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(entriesImport as any, 'analyzeEntryData').resolves([2, 2, 2, 10, 5]); sinon.stub(entriesImport as any, 'createNestedProgress').returns(mockProgress); @@ -2835,7 +2844,9 @@ describe('EntriesImport', () => { sinon.stub(entriesImport as any, 'processEntryCreation').resolves(); sinon.stub(entriesImport as any, 'processEntryReplacement').resolves(); sinon.stub(entriesImport as any, 'processEntryReferenceUpdates').resolves(); - const enableMandatoryCTReferencesStub = sinon.stub(entriesImport, 'enableMandatoryCTReferences').rejects(new Error('Enable failed')); + const enableMandatoryCTReferencesStub = sinon + .stub(entriesImport, 'enableMandatoryCTReferences') + .rejects(new Error('Enable failed')); sinon.stub(entriesImport, 'updateFieldRules').resolves(); sinon.stub(entriesImport as any, 'processEntryPublishing').resolves(); sinon.stub(entriesImport as any, 'processCleanup').resolves(); @@ -2850,15 +2861,22 @@ describe('EntriesImport', () => { it('should handle errors in updateFieldRules', async () => { const mockFsUtil = { - readFile: sinon.stub() - .onCall(0).resolves([mockData.simpleContentType]) - .onCall(1).resolves({ extension_uid: {} }) - .onCall(2).resolves({}) - .onCall(3).resolves({}) - .onCall(4).resolves({}) - .onCall(5).resolves([{ code: 'en-us' }]), + readFile: sinon + .stub() + .onCall(0) + .resolves([mockData.simpleContentType]) + .onCall(1) + .resolves({ extension_uid: {} }) + .onCall(2) + .resolves({}) + .onCall(3) + .resolves({}) + .onCall(4) + .resolves({}) + .onCall(5) + .resolves([{ code: 'en-us' }]), makeDirectory: sinon.stub().resolves(), - writeFile: sinon.stub().resolves() + writeFile: sinon.stub().resolves(), }; sinon.stub(require('../../../../src/utils'), 'fsUtil').value(mockFsUtil); @@ -2867,7 +2885,7 @@ describe('EntriesImport', () => { const mockFileHelper = { readFileSync: sinon.stub().returns({}), - writeLargeFile: sinon.stub().resolves() + writeLargeFile: sinon.stub().resolves(), }; sinon.stub(require('../../../../src/utils'), 'fileHelper').value(mockFileHelper); @@ -2876,7 +2894,7 @@ describe('EntriesImport', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(entriesImport as any, 'analyzeEntryData').resolves([2, 2, 2, 10, 5]); sinon.stub(entriesImport as any, 'createNestedProgress').returns(mockProgress); @@ -2897,7 +2915,9 @@ describe('EntriesImport', () => { sinon.stub(entriesImport as any, 'processEntryPublishing').resolves(); sinon.stub(entriesImport as any, 'processCleanup').resolves(); sinon.stub(entriesImport as any, 'removeAutoCreatedEntries').resolves(); - const updateFieldRulesStub = sinon.stub(entriesImport, 'updateFieldRules').rejects(new Error('Field rules failed')); + const updateFieldRulesStub = sinon + .stub(entriesImport, 'updateFieldRules') + .rejects(new Error('Field rules failed')); const createEntryDataForVariantEntryStub = sinon.stub(entriesImport, 'createEntryDataForVariantEntry').returns(); await entriesImport.start(); @@ -2912,7 +2932,7 @@ describe('EntriesImport', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(entriesImport as any, 'analyzeEntryData').resolves([2, 2, 2, 10, 5]); sinon.stub(entriesImport as any, 'createNestedProgress').returns(mockProgress); @@ -2941,7 +2961,7 @@ describe('EntriesImport', () => { const completeProgressStub = sinon.stub(entriesImport as any, 'completeProgress'); const createEntryDataForVariantEntryStub = sinon.stub(entriesImport, 'createEntryDataForVariantEntry').returns(); - await entriesImport.start(); + await entriesImport.start(); // Verify createEntryDataForVariantEntry was called in catch block expect(createEntryDataForVariantEntryStub.called).to.be.true; @@ -2966,12 +2986,12 @@ describe('EntriesImport', () => { it('should successfully remove auto-created entries', async () => { entriesImport['autoCreatedEntries'] = [ { entryUid: 'auto_entry_1', title: 'Auto Entry 1' }, - { entryUid: 'auto_entry_2', title: 'Auto Entry 2' } + { entryUid: 'auto_entry_2', title: 'Auto Entry 2' }, ]; entriesImport['entriesForVariant'] = [ { entry_uid: 'auto_entry_1', locale: 'en-us', content_type: 'simple_ct' }, { entry_uid: 'auto_entry_2', locale: 'en-us', content_type: 'ref_ct' }, - { entry_uid: 'other_entry', locale: 'fr-fr', content_type: 'simple_ct' } + { entry_uid: 'other_entry', locale: 'fr-fr', content_type: 'simple_ct' }, ]; // Use the existing makeConcurrentCall stub to simulate successful removal @@ -2979,12 +2999,12 @@ describe('EntriesImport', () => { // Simulate onSuccess callback for first entry await options.apiParams.resolve({ response: { uid: 'auto_entry_1' }, - apiData: { entryUid: 'auto_entry_1' } + apiData: { entryUid: 'auto_entry_1' }, }); // Simulate onSuccess callback for second entry await options.apiParams.resolve({ response: { uid: 'auto_entry_2' }, - apiData: { entryUid: 'auto_entry_2' } + apiData: { entryUid: 'auto_entry_2' }, }); }); @@ -3004,12 +3024,10 @@ describe('EntriesImport', () => { }); it('should handle errors when removing auto-created entries', async () => { - entriesImport['autoCreatedEntries'] = [ - { entryUid: 'auto_entry_1', title: 'Auto Entry 1' } - ]; + entriesImport['autoCreatedEntries'] = [{ entryUid: 'auto_entry_1', title: 'Auto Entry 1' }]; entriesImport['entriesForVariant'] = [ { entry_uid: 'auto_entry_1', locale: 'en-us', content_type: 'simple_ct' }, - { entry_uid: 'other_entry', locale: 'fr-fr', content_type: 'simple_ct' } + { entry_uid: 'other_entry', locale: 'fr-fr', content_type: 'simple_ct' }, ]; // Use the existing makeConcurrentCall stub to simulate error @@ -3017,7 +3035,7 @@ describe('EntriesImport', () => { // Simulate onReject callback await options.apiParams.reject({ error: new Error('Delete failed'), - apiData: { entryUid: 'auto_entry_1' } + apiData: { entryUid: 'auto_entry_1' }, }); }); @@ -3033,9 +3051,7 @@ describe('EntriesImport', () => { it('should handle empty auto-created entries array', async () => { entriesImport['autoCreatedEntries'] = []; - entriesImport['entriesForVariant'] = [ - { entry_uid: 'other_entry', locale: 'fr-fr', content_type: 'simple_ct' } - ]; + entriesImport['entriesForVariant'] = [{ entry_uid: 'other_entry', locale: 'fr-fr', content_type: 'simple_ct' }]; // Use the existing makeConcurrentCall stub makeConcurrentCallStub.resolves(); @@ -3052,7 +3068,7 @@ describe('EntriesImport', () => { it('should write file when entriesForVariant is not empty', () => { entriesImport['entriesForVariant'] = [ { entry_uid: 'entry_1', locale: 'en-us', content_type: 'simple_ct' }, - { entry_uid: 'entry_2', locale: 'fr-fr', content_type: 'ref_ct' } + { entry_uid: 'entry_2', locale: 'fr-fr', content_type: 'ref_ct' }, ]; const writeFileSyncStub = sinon.stub(require('fs'), 'writeFileSync'); @@ -3082,7 +3098,7 @@ describe('EntriesImport', () => { describe('updateFieldRules() Method Error Handling', () => { it('should handle content type fetch error', async () => { const mockContentTypes = [mockData.simpleContentType, mockData.contentTypeWithReferences]; - + fsUtilityReadFileStub.callsFake((filePath) => { console.log('fsUtil.readFile called with path:', filePath); if (filePath.includes('field_rules_uid.json')) { @@ -3098,19 +3114,18 @@ describe('EntriesImport', () => { }); const mockContentType = { - fetch: sinon.stub().rejects(new Error('Fetch failed')) + fetch: sinon.stub().rejects(new Error('Fetch failed')), }; const mockStackClient = { - contentType: sinon.stub().returns(mockContentType) + contentType: sinon.stub().returns(mockContentType), }; sinon.stub(entriesImport, 'stack').value(mockStackClient); - await entriesImport.updateFieldRules(); // Verify fsUtil.readFile was called expect(fsUtilityReadFileStub.callCount).to.be.greaterThan(0); - + // Verify stack client was called expect(mockStackClient.contentType.called).to.be.true; expect(mockContentType.fetch.called).to.be.true; @@ -3118,7 +3133,7 @@ describe('EntriesImport', () => { it('should handle content type update error', async () => { const mockContentTypes = [mockData.simpleContentType, mockData.contentTypeWithReferences]; - + fsUtilityReadFileStub.callsFake((path) => { if (path.includes('field_rules_uid.json')) { return ['simple_ct']; // array of strings @@ -3131,23 +3146,22 @@ describe('EntriesImport', () => { const mockUpdate = sinon.stub().rejects(new Error('Update failed')); const mockContentType = { - fetch: sinon.stub().resolves({ - uid: 'simple_ct', + fetch: sinon.stub().resolves({ + uid: 'simple_ct', field_rules: [], - update: mockUpdate - }) + update: mockUpdate, + }), }; const mockStackClient = { - contentType: sinon.stub().returns(mockContentType) + contentType: sinon.stub().returns(mockContentType), }; sinon.stub(entriesImport, 'stack').value(mockStackClient); - await entriesImport.updateFieldRules(); // Verify fsUtil.readFile was called expect(fsUtilityReadFileStub.callCount).to.be.greaterThan(0); - + // Verify stack client was called expect(mockStackClient.contentType.called).to.be.true; expect(mockContentType.fetch.called).to.be.true; @@ -3156,7 +3170,7 @@ describe('EntriesImport', () => { it('should skip when content type not found', async () => { const mockContentTypes = [mockData.simpleContentType, mockData.contentTypeWithReferences]; - + fsUtilityReadFileStub.callsFake((path) => { if (path.includes('field_rules_uid.json')) { return ['simple_ct']; // array of strings @@ -3168,10 +3182,10 @@ describe('EntriesImport', () => { }); const mockContentType = { - fetch: sinon.stub().resolves(null) + fetch: sinon.stub().resolves(null), }; const mockStackClient = { - contentType: sinon.stub().returns(mockContentType) + contentType: sinon.stub().returns(mockContentType), }; sinon.stub(entriesImport, 'stack').value(mockStackClient); @@ -3180,7 +3194,7 @@ describe('EntriesImport', () => { info: sinon.stub(), success: sinon.stub(), warn: sinon.stub(), - error: sinon.stub() + error: sinon.stub(), }; sinon.stub(require('@contentstack/cli-utilities'), 'log').value(mockLog); @@ -3188,9 +3202,9 @@ describe('EntriesImport', () => { // Verify debug log was called for skipping expect(mockLog.debug.called).to.be.true; - const skipCall = mockLog.debug.getCalls().find((call: any) => - call.args[0] && call.args[0].includes('Skipping field rules update') - ); + const skipCall = mockLog.debug + .getCalls() + .find((call: any) => call.args[0] && call.args[0].includes('Skipping field rules update')); expect(skipCall).to.exist; }); @@ -3198,7 +3212,7 @@ describe('EntriesImport', () => { const contentTypeWithoutRules = { ...mockData.simpleContentType }; delete contentTypeWithoutRules.field_rules; const mockContentTypes = [contentTypeWithoutRules]; - + fsUtilityReadFileStub.callsFake((path) => { if (path.includes('field_rules_uid.json')) { return ['simple_ct']; // array of strings @@ -3214,7 +3228,7 @@ describe('EntriesImport', () => { info: sinon.stub(), success: sinon.stub(), warn: sinon.stub(), - error: sinon.stub() + error: sinon.stub(), }; sinon.stub(require('@contentstack/cli-utilities'), 'log').value(mockLog); @@ -3222,9 +3236,9 @@ describe('EntriesImport', () => { // Verify info log was called for no field rules expect(mockLog.info.called).to.be.true; - const noRulesCall = mockLog.info.getCalls().find((call: any) => - call.args[0] && call.args[0].includes('No field rules found') - ); + const noRulesCall = mockLog.info + .getCalls() + .find((call: any) => call.args[0] && call.args[0].includes('No field rules found')); expect(noRulesCall).to.exist; }); }); @@ -3234,15 +3248,15 @@ describe('EntriesImport', () => { const entry = { uid: 'localized_entry_1', title: 'Localized Entry', - description: 'A localized entry' + description: 'A localized entry', }; const contentType = mockData.simpleContentType; const isMasterLocale = false; entriesImport['entriesUidMapper'] = { - 'localized_entry_1': 'new_localized_entry_1' + localized_entry_1: 'new_localized_entry_1', }; - + entriesImport['assetUidMapper'] = {}; entriesImport['assetUrlMapper'] = {}; entriesImport['installedExtensions'] = []; @@ -3250,19 +3264,19 @@ describe('EntriesImport', () => { const originalLookupAssets = require('../../../../src/utils').lookupAssets; Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { get: () => (entryData: any) => entryData.entry, - configurable: true + configurable: true, }); const mockEntryResponse = { uid: 'new_localized_entry_1', title: 'Localized Entry', - description: 'A localized entry' + description: 'A localized entry', }; const mockContentType = { - entry: sinon.stub().returns(mockEntryResponse) + entry: sinon.stub().returns(mockEntryResponse), }; const mockStackClient = { - contentType: sinon.stub().returns(mockContentType) + contentType: sinon.stub().returns(mockContentType), }; sinon.stub(entriesImport, 'stack').value(mockStackClient); @@ -3271,7 +3285,7 @@ describe('EntriesImport', () => { apiData: entry, resolve: sinon.stub(), reject: sinon.stub(), - additionalInfo: { cTUid: 'simple_ct', locale: 'fr-fr', contentType, isMasterLocale } + additionalInfo: { cTUid: 'simple_ct', locale: 'fr-fr', contentType, isMasterLocale }, }; const result = entriesImport.serializeEntries(apiOptions); @@ -3282,12 +3296,12 @@ describe('EntriesImport', () => { expect(result.apiData.title).to.equal('Localized Entry'); expect(result.additionalInfo['new_localized_entry_1']).to.deep.equal({ isLocalized: true, - entryOldUid: 'localized_entry_1' + entryOldUid: 'localized_entry_1', }); Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { value: originalLookupAssets, - configurable: true + configurable: true, }); }); @@ -3295,13 +3309,13 @@ describe('EntriesImport', () => { const entry = { uid: 'localized_entry_1', title: 'Localized Entry', - description: 'A localized entry' + description: 'A localized entry', }; const contentType = mockData.simpleContentType; const isMasterLocale = false; entriesImport['entriesUidMapper'] = {}; - + entriesImport['assetUidMapper'] = {}; entriesImport['assetUrlMapper'] = {}; entriesImport['installedExtensions'] = []; @@ -3309,7 +3323,7 @@ describe('EntriesImport', () => { const originalLookupAssets = require('../../../../src/utils').lookupAssets; Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { get: () => (entryData: any) => entryData.entry, - configurable: true + configurable: true, }); const apiOptions = { @@ -3317,7 +3331,7 @@ describe('EntriesImport', () => { apiData: entry, resolve: sinon.stub(), reject: sinon.stub(), - additionalInfo: { cTUid: 'simple_ct', locale: 'fr-fr', contentType, isMasterLocale } + additionalInfo: { cTUid: 'simple_ct', locale: 'fr-fr', contentType, isMasterLocale }, }; const result = entriesImport.serializeEntries(apiOptions); @@ -3330,7 +3344,7 @@ describe('EntriesImport', () => { Object.defineProperty(require('../../../../src/utils'), 'lookupAssets', { value: originalLookupAssets, - configurable: true + configurable: true, }); }); }); @@ -3340,7 +3354,7 @@ describe('EntriesImport', () => { entriesImport['entriesForVariant'] = [ { entry_uid: 'entry_1', locale: 'en-us', content_type: 'simple_ct' }, { entry_uid: 'entry_2', locale: 'fr-fr', content_type: 'ref_ct' }, - { entry_uid: 'entry_3', locale: 'en-us', content_type: 'simple_ct' } + { entry_uid: 'entry_3', locale: 'en-us', content_type: 'simple_ct' }, ]; // Use the existing makeConcurrentCall stub to trigger onReject @@ -3348,19 +3362,19 @@ describe('EntriesImport', () => { // Simulate onReject callback - uid should match entry_uid in entriesForVariant await options.apiParams.reject({ error: new Error('Update failed'), - apiData: { uid: 'entry_1', title: 'Entry 1' } + apiData: { uid: 'entry_1', title: 'Entry 1' }, }); }); const handleAndLogErrorStub = sinon.stub(require('@contentstack/cli-utilities'), 'handleAndLogError'); - const mockIndexFileContent = { 'chunk1': true }; + const mockIndexFileContent = { chunk1: true }; sinon.stub(FsUtility.prototype, 'indexFileContent').get(() => mockIndexFileContent); const mockReadChunkFiles = { next: sinon.stub().resolves({ - 'entry1': { uid: 'entry_1', title: 'Entry 1' } - }) + entry1: { uid: 'entry_1', title: 'Entry 1' }, + }), }; sinon.stub(FsUtility.prototype, 'readChunkFiles').get(() => mockReadChunkFiles); @@ -3370,11 +3384,10 @@ describe('EntriesImport', () => { // Verify entriesForVariant was filtered correctly expect(entriesImport['entriesForVariant']).to.have.length(2); - expect(entriesImport['entriesForVariant'].find(e => e.entry_uid === 'entry_1')).to.be.undefined; - expect(entriesImport['entriesForVariant'].find(e => e.entry_uid === 'entry_2')).to.exist; - expect(entriesImport['entriesForVariant'].find(e => e.entry_uid === 'entry_3')).to.exist; + expect(entriesImport['entriesForVariant'].find((e) => e.entry_uid === 'entry_1')).to.be.undefined; + expect(entriesImport['entriesForVariant'].find((e) => e.entry_uid === 'entry_2')).to.exist; + expect(entriesImport['entriesForVariant'].find((e) => e.entry_uid === 'entry_3')).to.exist; }); - }); }); @@ -3388,26 +3401,26 @@ describe('EntriesImport', () => { beforeEach(() => { sinon.restore(); - + sinon.stub(FsUtility.prototype, 'createFolderIfNotExist').callsFake(() => { return Promise.resolve(); }); - + // Recreate entriesImport instance after restore progressEntriesImport = new EntriesImport({ importConfig: mockImportConfig as any, stackAPIClient: mockStackClient, - moduleName: 'entries' + moduleName: 'entries', }); - + // Initialize required properties (will be set by analyzeEntryData from mocks) - + mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; }); @@ -3429,18 +3442,20 @@ describe('EntriesImport', () => { it('should return zeros when no content types found', async () => { const fsUtilReadFileStub = sinon.stub(fsUtil, 'readFile').resolves([]); const fsUtilMakeDirectoryStub = sinon.stub(fsUtil, 'makeDirectory').resolves(); - + const isEmptyStub = sinon.stub().returns(true); sinon.stub(require('lodash'), 'isEmpty').value(isEmptyStub); - sinon.stub(progressEntriesImport as any, 'withLoadingSpinner').callsFake(async (message: string, action: () => Promise) => { - return await action(); - }); + sinon + .stub(progressEntriesImport as any, 'withLoadingSpinner') + .callsFake(async (message: string, action: () => Promise) => { + return await action(); + }); const result = await progressEntriesImport['analyzeEntryData'](); expect(result).to.deep.equal([0, 0, 0, 0, 0]); - + fsUtilReadFileStub.restore(); fsUtilMakeDirectoryStub.restore(); }); @@ -3453,7 +3468,7 @@ describe('EntriesImport', () => { localesCount: 2, totalEntryChunks: 5, totalActualEntries: 10, - totalEntriesForPublishing: 5 + totalEntriesForPublishing: 5, }; progressEntriesImport['importConfig'].replaceExisting = false; @@ -3471,7 +3486,7 @@ describe('EntriesImport', () => { localesCount: 2, totalEntryChunks: 5, totalActualEntries: 10, - totalEntriesForPublishing: 5 + totalEntriesForPublishing: 5, }; progressEntriesImport['importConfig'].replaceExisting = true; @@ -3488,7 +3503,7 @@ describe('EntriesImport', () => { localesCount: 2, totalEntryChunks: 5, totalActualEntries: 10, - totalEntriesForPublishing: 5 + totalEntriesForPublishing: 5, }; progressEntriesImport['importConfig'].replaceExisting = false; @@ -3504,10 +3519,10 @@ describe('EntriesImport', () => { it('should process entry creation successfully', async () => { const writeFileStub = sinon.stub(fsUtil, 'writeFile').resolves(); const writeLargeFileStub = sinon.stub(fileHelper, 'writeLargeFile').resolves(); - - const populateStub = sinon.stub(progressEntriesImport, 'populateEntryCreatePayload').returns([ - { cTUid: 'simple_ct', locale: 'en-us' } - ]); + + const populateStub = sinon + .stub(progressEntriesImport, 'populateEntryCreatePayload') + .returns([{ cTUid: 'simple_ct', locale: 'en-us' }]); const createEntriesStub = sinon.stub(progressEntriesImport, 'createEntries').resolves(); await progressEntriesImport['processEntryCreation'](); @@ -3521,9 +3536,9 @@ describe('EntriesImport', () => { describe('processEntryReplacement()', () => { it('should process entry replacement successfully', async () => { - const populateStub = sinon.stub(progressEntriesImport, 'populateEntryCreatePayload').returns([ - { cTUid: 'simple_ct', locale: 'en-us' } - ]); + const populateStub = sinon + .stub(progressEntriesImport, 'populateEntryCreatePayload') + .returns([{ cTUid: 'simple_ct', locale: 'en-us' }]); const replaceEntriesStub = sinon.stub(progressEntriesImport, 'replaceEntries').resolves(); await progressEntriesImport['processEntryReplacement'](); @@ -3533,10 +3548,12 @@ describe('EntriesImport', () => { }); it('should handle errors in replaceEntries gracefully', async () => { - const populateStub = sinon.stub(progressEntriesImport, 'populateEntryCreatePayload').returns([ - { cTUid: 'simple_ct', locale: 'en-us' } - ]); - const replaceEntriesStub = sinon.stub(progressEntriesImport, 'replaceEntries').rejects(new Error('Replace failed')); + const populateStub = sinon + .stub(progressEntriesImport, 'populateEntryCreatePayload') + .returns([{ cTUid: 'simple_ct', locale: 'en-us' }]); + const replaceEntriesStub = sinon + .stub(progressEntriesImport, 'replaceEntries') + .rejects(new Error('Replace failed')); const handleErrorStub = sinon.stub(require('@contentstack/cli-utilities'), 'handleAndLogError'); await progressEntriesImport['processEntryReplacement'](); @@ -3552,9 +3569,9 @@ describe('EntriesImport', () => { }); it('should process entry reference updates successfully', async () => { - const populateStub = sinon.stub(progressEntriesImport, 'populateEntryUpdatePayload').returns([ - { cTUid: 'simple_ct', locale: 'en-us' } - ]); + const populateStub = sinon + .stub(progressEntriesImport, 'populateEntryUpdatePayload') + .returns([{ cTUid: 'simple_ct', locale: 'en-us' }]); const updateStub = sinon.stub(progressEntriesImport, 'updateEntriesWithReferences').resolves(); await progressEntriesImport['processEntryReferenceUpdates'](); @@ -3565,10 +3582,12 @@ describe('EntriesImport', () => { }); it('should handle errors in updateEntriesWithReferences gracefully', async () => { - const populateStub = sinon.stub(progressEntriesImport, 'populateEntryUpdatePayload').returns([ - { cTUid: 'simple_ct', locale: 'en-us' } - ]); - const updateStub = sinon.stub(progressEntriesImport, 'updateEntriesWithReferences').rejects(new Error('Update failed')); + const populateStub = sinon + .stub(progressEntriesImport, 'populateEntryUpdatePayload') + .returns([{ cTUid: 'simple_ct', locale: 'en-us' }]); + const updateStub = sinon + .stub(progressEntriesImport, 'updateEntriesWithReferences') + .rejects(new Error('Update failed')); const handleErrorStub = sinon.stub(require('@contentstack/cli-utilities'), 'handleAndLogError'); try { @@ -3585,15 +3604,15 @@ describe('EntriesImport', () => { describe('processEntryPublishing()', () => { beforeEach(() => { progressEntriesImport['envs'] = { - 'env_1': { name: 'production', uid: 'env_1' } + env_1: { name: 'production', uid: 'env_1' }, }; sinon.stub(fileHelper, 'readFileSync').returns(progressEntriesImport['envs']); }); it('should process entry publishing successfully', async () => { - const populateStub = sinon.stub(progressEntriesImport, 'populateEntryCreatePayload').returns([ - { cTUid: 'simple_ct', locale: 'en-us' } - ]); + const populateStub = sinon + .stub(progressEntriesImport, 'populateEntryCreatePayload') + .returns([{ cTUid: 'simple_ct', locale: 'en-us' }]); const publishStub = sinon.stub(progressEntriesImport, 'publishEntries').resolves(); await progressEntriesImport['processEntryPublishing'](); @@ -3605,9 +3624,9 @@ describe('EntriesImport', () => { it('should handle errors in publishEntries gracefully', async () => { const handleErrorStub = sinon.stub(require('@contentstack/cli-utilities'), 'handleAndLogError'); - const populateStub = sinon.stub(progressEntriesImport, 'populateEntryCreatePayload').returns([ - { cTUid: 'simple_ct', locale: 'en-us' } - ]); + const populateStub = sinon + .stub(progressEntriesImport, 'populateEntryCreatePayload') + .returns([{ cTUid: 'simple_ct', locale: 'en-us' }]); const publishStub = sinon.stub(progressEntriesImport, 'publishEntries').rejects(new Error('Publish failed')); await progressEntriesImport['processEntryPublishing'](); @@ -3620,9 +3639,7 @@ describe('EntriesImport', () => { describe('processCleanup()', () => { it('should process cleanup successfully when autoCreatedEntries exist', async () => { - progressEntriesImport['autoCreatedEntries'] = [ - { cTUid: 'simple_ct', locale: 'en-us', entryUid: 'entry_1' } - ]; + progressEntriesImport['autoCreatedEntries'] = [{ cTUid: 'simple_ct', locale: 'en-us', entryUid: 'entry_1' }]; progressEntriesImport['progressManager'] = mockProgress; const removeStub = sinon.stub(progressEntriesImport, 'removeAutoCreatedEntries').resolves(); const createVariantStub = sinon.stub(progressEntriesImport, 'createEntryDataForVariantEntry').returns(); @@ -3644,10 +3661,10 @@ describe('EntriesImport', () => { }); it('should handle errors in removeAutoCreatedEntries gracefully', async () => { - progressEntriesImport['autoCreatedEntries'] = [ - { cTUid: 'simple_ct', locale: 'en-us', entryUid: 'entry_1' } - ]; - const removeStub = sinon.stub(progressEntriesImport, 'removeAutoCreatedEntries').rejects(new Error('Remove failed')); + progressEntriesImport['autoCreatedEntries'] = [{ cTUid: 'simple_ct', locale: 'en-us', entryUid: 'entry_1' }]; + const removeStub = sinon + .stub(progressEntriesImport, 'removeAutoCreatedEntries') + .rejects(new Error('Remove failed')); const handleErrorStub = sinon.stub(require('@contentstack/cli-utilities'), 'handleAndLogError'); const createVariantStub = sinon.stub(progressEntriesImport, 'createEntryDataForVariantEntry').returns(); diff --git a/packages/contentstack-import/test/unit/import/modules/global-fields.test.ts b/packages/contentstack-import/test/unit/import/modules/global-fields.test.ts index 9710fb9921..4efd0d7ea7 100644 --- a/packages/contentstack-import/test/unit/import/modules/global-fields.test.ts +++ b/packages/contentstack-import/test/unit/import/modules/global-fields.test.ts @@ -20,14 +20,14 @@ describe('ImportGlobalFields', () => { fsUtilStub = { readFile: sinon.stub(), writeFile: sinon.stub(), - makeDirectory: sinon.stub().resolves() + makeDirectory: sinon.stub().resolves(), }; sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); fileHelperStub = { - fileExistsSync: sinon.stub().returns(false) + fileExistsSync: sinon.stub().returns(false), }; sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); @@ -36,17 +36,18 @@ describe('ImportGlobalFields', () => { mockStackClient = { globalField: sinon.stub().returns({ - fetch: sinon.stub().resolves({ uid: 'gf-123', title: 'Test GF', update: sinon.stub().resolves({ uid: 'gf-123' }) }), + fetch: sinon + .stub() + .resolves({ uid: 'gf-123', title: 'Test GF', update: sinon.stub().resolves({ uid: 'gf-123' }) }), update: sinon.stub().resolves({ uid: 'gf-123', title: 'Updated GF' }), - create: sinon.stub().resolves({ uid: 'gf-123', title: 'Test GF' }) - }) + create: sinon.stub().resolves({ uid: 'gf-123', title: 'Test GF' }), + }), }; mockImportConfig = { apiKey: 'test', contentDir: '/test/content', data: '/test/content', - contentVersion: 1, region: 'us', master_locale: { code: 'en-us' }, masterLocale: { code: 'en-us' }, @@ -59,7 +60,7 @@ describe('ImportGlobalFields', () => { sessionId: 'session-123', apiKey: 'test', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, modules: { types: ['global-fields'], @@ -69,8 +70,8 @@ describe('ImportGlobalFields', () => { apiConcurrency: 5, writeConcurrency: 3, fileName: 'globalfields.json', - limit: 100 - } + limit: 100, + }, }, backupDir: '/test/backup', cliLogsPath: '/test/logs', @@ -84,13 +85,13 @@ describe('ImportGlobalFields', () => { preserveStackVersion: false, replaceExisting: false, skipExisting: false, - 'exclude-global-modules': false + 'exclude-global-modules': false, } as any; importGlobalFields = new ImportGlobalFields({ importConfig: mockImportConfig as any, stackAPIClient: mockStackClient, - moduleName: 'global-fields' + moduleName: 'global-fields', }); makeConcurrentCallStub = sinon.stub(importGlobalFields as any, 'makeConcurrentCall').resolves(); @@ -139,7 +140,7 @@ describe('ImportGlobalFields', () => { const instance = new ImportGlobalFields({ importConfig: config as any, stackAPIClient: mockStackClient, - moduleName: 'global-fields' + moduleName: 'global-fields', }); expect(instance['reqConcurrency']).to.equal(2); }); @@ -148,12 +149,12 @@ describe('ImportGlobalFields', () => { describe('start()', () => { it('should return early when no global fields found', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([0]); await importGlobalFields.start(); @@ -163,12 +164,12 @@ describe('ImportGlobalFields', () => { it('should return early when global fields array is empty', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([0]); await importGlobalFields.start(); @@ -182,19 +183,21 @@ describe('ImportGlobalFields', () => { sinon.stub(fsUtil, 'writeFile'); sinon.stub(fsUtil, 'makeDirectory'); sinon.stub(fileHelper, 'fileExistsSync'); - + const seedGFsStub = sinon.stub(importGlobalFields as any, 'seedGFs').resolves(); const updateGFsStub = sinon.stub(importGlobalFields as any, 'updateGFs').resolves(); - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([2]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -209,12 +212,12 @@ describe('ImportGlobalFields', () => { it('should load existing UID mapper when file exists', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; const mockUidMapper = { gf1: 'mapped-gf1' }; @@ -224,16 +227,18 @@ describe('ImportGlobalFields', () => { fsUtilStub.readFile.withArgs(sinon.match(/uid-mapping\.json/)).returns(mockUidMapper); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'seedGFs').resolves(); @@ -258,10 +263,12 @@ describe('ImportGlobalFields', () => { sinon.stub(fsUtil, 'writeFile'); sinon.stub(fsUtil, 'makeDirectory'); sinon.stub(fileHelper, 'fileExistsSync'); - - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').callsFake(async () => { (importGlobalFields as any).installedExtensions = { ext1: 'uid1', ext2: 'uid2' }; return [1]; @@ -271,7 +278,7 @@ describe('ImportGlobalFields', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -287,28 +294,30 @@ describe('ImportGlobalFields', () => { it('should write pending global fields when available', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); importGlobalFields['pendingGFs'] = ['gf1', 'gf2']; - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -324,28 +333,30 @@ describe('ImportGlobalFields', () => { it('should write success file when global fields created', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); importGlobalFields['createdGFs'] = [{ uid: 'gf1' }, { uid: 'gf2' }]; - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -361,28 +372,30 @@ describe('ImportGlobalFields', () => { it('should write fails file when global fields failed', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); importGlobalFields['failedGFs'] = [{ uid: 'gf1' }]; - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -398,12 +411,12 @@ describe('ImportGlobalFields', () => { it('should call replaceGFs when replaceExisting is true and existingGFs exist', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; importGlobalFields['importConfig'].replaceExisting = true; importGlobalFields['existingGFs'] = [{ uid: 'gf1', global_field: { uid: 'gf1' } }]; @@ -411,16 +424,18 @@ describe('ImportGlobalFields', () => { fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -440,12 +455,12 @@ describe('ImportGlobalFields', () => { it('should handle replaceGFs errors gracefully', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; importGlobalFields['importConfig'].replaceExisting = true; importGlobalFields['existingGFs'] = [{ uid: 'gf1', global_field: { uid: 'gf1' } }]; @@ -453,16 +468,18 @@ describe('ImportGlobalFields', () => { fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -518,7 +535,7 @@ describe('ImportGlobalFields', () => { const mockGF = { global_field: { uid: 'gf1' } }; onReject({ error: { errors: { title: 'exists' } }, - apiData: mockGF + apiData: mockGF, }); expect(importGlobalFields['existingGFs']).to.include(mockGF); @@ -533,7 +550,7 @@ describe('ImportGlobalFields', () => { const onReject = makeConcurrentCallStub.firstCall.args[0].apiParams.reject; onReject({ error: { errors: { title: 'exists' } }, - apiData: { global_field: { uid: 'gf1' } } + apiData: { global_field: { uid: 'gf1' } }, }); // Should not throw, just log @@ -547,7 +564,7 @@ describe('ImportGlobalFields', () => { const onReject = makeConcurrentCallStub.firstCall.args[0].apiParams.reject; onReject({ error: { errorCode: 500, message: 'Server error' }, - apiData: { global_field: { uid: 'gf1' } } + apiData: { global_field: { uid: 'gf1' } }, }); expect(importGlobalFields['failedGFs']).to.have.lengthOf(1); @@ -565,7 +582,7 @@ describe('ImportGlobalFields', () => { describe('serializeGFs()', () => { it('should serialize global field correctly', () => { const apiOptions = { - apiData: { uid: 'test_gf', title: 'Test Global Field', schema: [] as any } + apiData: { uid: 'test_gf', title: 'Test Global Field', schema: [] as any }, }; const result = importGlobalFields.serializeGFs(apiOptions as any); @@ -577,7 +594,7 @@ describe('ImportGlobalFields', () => { it('should use gfSchemaTemplate structure', () => { const apiOptions = { - apiData: { uid: 'gf_uid', title: 'GF Title', schema: [] as any } + apiData: { uid: 'gf_uid', title: 'GF Title', schema: [] as any }, }; const result = importGlobalFields.serializeGFs(apiOptions as any); @@ -604,9 +621,9 @@ describe('ImportGlobalFields', () => { await importGlobalFields.updateGFs(); expect(makeConcurrentCallStub.called).to.be.true; - const callArgs = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update Global Fields' - )?.args[0]; + const callArgs = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update Global Fields')?.args[0]; expect(callArgs.processName).to.equal('Update Global Fields'); expect(callArgs.apiParams.entity).to.equal('update-gfs'); }); @@ -618,9 +635,9 @@ describe('ImportGlobalFields', () => { await importGlobalFields.updateGFs(); expect(makeConcurrentCallStub.called).to.be.true; - const serializeFunc = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update Global Fields' - )?.args[1]; + const serializeFunc = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update Global Fields')?.args[1]; expect(serializeFunc).to.be.a('function'); }); @@ -629,9 +646,9 @@ describe('ImportGlobalFields', () => { await importGlobalFields.updateGFs(); - const onSuccess = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update Global Fields' - )?.args[0].apiParams.resolve; + const onSuccess = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update Global Fields')?.args[0].apiParams.resolve; expect(() => { onSuccess({ response: {}, apiData: { uid: 'gf1' } }); @@ -643,9 +660,9 @@ describe('ImportGlobalFields', () => { await importGlobalFields.updateGFs(); - const onReject = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update Global Fields' - )?.args[0].apiParams.reject; + const onReject = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update Global Fields')?.args[0].apiParams.reject; expect(() => { onReject({ error: { message: 'Update failed' }, apiData: { uid: 'gf1' } }); @@ -669,7 +686,7 @@ describe('ImportGlobalFields', () => { mockGlobalField = { uid: 'gf1', title: 'GF 1', schema: [] }; mockApiParams = { resolve: sinon.stub(), - reject: sinon.stub() + reject: sinon.stub(), }; importGlobalFields['installedExtensions'] = {}; importGlobalFields['config'] = mockImportConfig; @@ -679,7 +696,7 @@ describe('ImportGlobalFields', () => { await importGlobalFields.updateSerializedGFs({ apiParams: mockApiParams, element: mockGlobalField, - isLastRequest: false + isLastRequest: false, }); expect(lookupExtensionStub.calledOnce).to.be.true; @@ -689,7 +706,7 @@ describe('ImportGlobalFields', () => { await importGlobalFields.updateSerializedGFs({ apiParams: mockApiParams, element: mockGlobalField, - isLastRequest: false + isLastRequest: false, }); expect(removeReferenceFieldsStub.calledOnce).to.be.true; @@ -703,7 +720,7 @@ describe('ImportGlobalFields', () => { await importGlobalFields.updateSerializedGFs({ apiParams: mockApiParams, element: mockGlobalField, - isLastRequest: false + isLastRequest: false, }); expect(importGlobalFields['pendingGFs']).to.include('gf1'); @@ -713,13 +730,13 @@ describe('ImportGlobalFields', () => { it('should fetch and update global field when not suppressed', async () => { const mockResponse = { uid: 'gf1', update: sinon.stub().resolves({ uid: 'gf1' }) }; mockStackClient.globalField.returns({ - fetch: sinon.stub().resolves(mockResponse) + fetch: sinon.stub().resolves(mockResponse), }); await importGlobalFields.updateSerializedGFs({ apiParams: mockApiParams, element: mockGlobalField, - isLastRequest: false + isLastRequest: false, }); expect(mockStackClient.globalField.calledWith('gf1', { api_version: '3.2' })).to.be.true; @@ -728,14 +745,14 @@ describe('ImportGlobalFields', () => { it('should handle fetch error', async () => { mockStackClient.globalField.returns({ - fetch: sinon.stub().rejects(new Error('Fetch failed')) + fetch: sinon.stub().rejects(new Error('Fetch failed')), }); try { await importGlobalFields.updateSerializedGFs({ apiParams: mockApiParams, element: mockGlobalField, - isLastRequest: false + isLastRequest: false, }); expect.fail('Should have thrown an error'); } catch (error) { @@ -748,14 +765,14 @@ describe('ImportGlobalFields', () => { it('should handle update error', async () => { const mockResponse = { uid: 'gf1', update: sinon.stub().rejects(new Error('Update failed')) }; mockStackClient.globalField.returns({ - fetch: sinon.stub().resolves(mockResponse) + fetch: sinon.stub().resolves(mockResponse), }); try { await importGlobalFields.updateSerializedGFs({ apiParams: mockApiParams, element: mockGlobalField, - isLastRequest: false + isLastRequest: false, }); expect.fail('Should have thrown an error'); } catch (error) { @@ -770,16 +787,16 @@ describe('ImportGlobalFields', () => { beforeEach(() => { importGlobalFields['existingGFs'] = [ { uid: 'gf1', global_field: { uid: 'gf1' } }, - { uid: 'gf2', global_field: { uid: 'gf2' } } + { uid: 'gf2', global_field: { uid: 'gf2' } }, ]; }); it('should call makeConcurrentCall with correct parameters', async () => { await importGlobalFields.replaceGFs(); - const callArgs = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0]; + const callArgs = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0]; expect(callArgs.processName).to.equal('Replace global fields'); expect(callArgs.apiContent).to.equal(importGlobalFields['existingGFs']); expect(callArgs.apiParams.entity).to.equal('update-gfs'); @@ -788,9 +805,9 @@ describe('ImportGlobalFields', () => { it('should handle successful replacement', async () => { await importGlobalFields.replaceGFs(); - const onSuccess = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0].apiParams.resolve; + const onSuccess = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0].apiParams.resolve; const mockGF = { uid: 'gf1', title: 'GF 1' }; onSuccess({ response: mockGF, apiData: { uid: 'gf1' } }); @@ -802,9 +819,9 @@ describe('ImportGlobalFields', () => { it('should handle replacement with global_field nested uid', async () => { await importGlobalFields.replaceGFs(); - const onSuccess = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0].apiParams.resolve; + const onSuccess = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0].apiParams.resolve; const mockGF = { uid: 'gf1', title: 'GF 1' }; onSuccess({ response: mockGF, apiData: { global_field: { uid: 'gf1' } } }); @@ -815,9 +832,9 @@ describe('ImportGlobalFields', () => { it('should handle replacement failure', async () => { await importGlobalFields.replaceGFs(); - const onReject = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0].apiParams.reject; + const onReject = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0].apiParams.reject; onReject({ error: { message: 'Replace failed' }, apiData: { uid: 'gf1' } }); @@ -827,9 +844,9 @@ describe('ImportGlobalFields', () => { it('should use correct concurrency', async () => { await importGlobalFields.replaceGFs(); - const callArgs = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0]; + const callArgs = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0]; expect(callArgs.concurrencyLimit).to.be.a('number'); }); }); @@ -838,13 +855,13 @@ describe('ImportGlobalFields', () => { beforeEach(() => { mockStackClient.globalField.returns({ uid: 'test_gf', - stackHeaders: { 'test-header': 'value' } + stackHeaders: { 'test-header': 'value' }, }); }); it('should serialize global field replacement correctly', () => { const apiOptions = { - apiData: { uid: 'gf1', title: 'GF 1', schema: [] as any } + apiData: { uid: 'gf1', title: 'GF 1', schema: [] as any }, }; const result = importGlobalFields.serializeReplaceGFs(apiOptions as any); @@ -855,7 +872,7 @@ describe('ImportGlobalFields', () => { it('should handle global field with nested uid', () => { const apiOptions = { - apiData: { global_field: { uid: 'gf1' }, title: 'GF 1' } + apiData: { global_field: { uid: 'gf1' }, title: 'GF 1' }, }; const result = importGlobalFields.serializeReplaceGFs(apiOptions as any); @@ -865,7 +882,7 @@ describe('ImportGlobalFields', () => { it('should preserve stackHeaders', () => { const apiOptions = { - apiData: { uid: 'gf1', title: 'GF 1', schema: [] as any } + apiData: { uid: 'gf1', title: 'GF 1', schema: [] as any }, }; const result = importGlobalFields.serializeReplaceGFs(apiOptions as any); @@ -886,10 +903,12 @@ describe('ImportGlobalFields', () => { sinon.stub(fsUtil, 'writeFile'); sinon.stub(fsUtil, 'makeDirectory'); sinon.stub(fileHelper, 'fileExistsSync'); - - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').callsFake(async () => { (importGlobalFields as any).installedExtensions = {}; return [0]; @@ -899,7 +918,7 @@ describe('ImportGlobalFields', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'completeProgress').resolves(); @@ -917,7 +936,7 @@ describe('ImportGlobalFields', () => { const onReject = makeConcurrentCallStub.firstCall.args[0].apiParams.reject; onReject({ error: { errorCode: 500, message: 'Server error' }, // No errors.title - apiData: { global_field: { uid: 'gf1' } } + apiData: { global_field: { uid: 'gf1' } }, }); expect(importGlobalFields['failedGFs']).to.have.lengthOf(1); @@ -932,7 +951,7 @@ describe('ImportGlobalFields', () => { const onReject = makeConcurrentCallStub.firstCall.args[0].apiParams.reject; onReject({ error: { errors: { title: 'exists' } }, - apiData: { global_field: { uid: 'gf1' } } + apiData: { global_field: { uid: 'gf1' } }, }); // Should not log "already exist" message when skipExisting is true @@ -944,9 +963,9 @@ describe('ImportGlobalFields', () => { await importGlobalFields.updateGFs(); - const onSuccess = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update Global Fields' - )?.args[0].apiParams.resolve; + const onSuccess = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update Global Fields')?.args[0].apiParams.resolve; expect(() => { onSuccess({ response: { uid: 'gf1' }, apiData: { uid: 'gf1' } }); @@ -958,9 +977,9 @@ describe('ImportGlobalFields', () => { await importGlobalFields.updateGFs(); - const onReject = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update Global Fields' - )?.args[0].apiParams.reject; + const onReject = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update Global Fields')?.args[0].apiParams.reject; expect(() => { onReject({ error: { message: 'Update failed' }, apiData: { uid: 'gf1' } }); @@ -968,15 +987,13 @@ describe('ImportGlobalFields', () => { }); it('should handle replaceGFs onSuccess with apiData.uid', async () => { - importGlobalFields['existingGFs'] = [ - { uid: 'gf1', global_field: { uid: 'gf1' } } - ]; + importGlobalFields['existingGFs'] = [{ uid: 'gf1', global_field: { uid: 'gf1' } }]; await importGlobalFields.replaceGFs(); - const onSuccess = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0].apiParams.resolve; + const onSuccess = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0].apiParams.resolve; const mockGF = { uid: 'gf1', title: 'GF 1' }; onSuccess({ response: mockGF, apiData: { uid: 'gf1' } }); @@ -986,15 +1003,13 @@ describe('ImportGlobalFields', () => { }); it('should handle replaceGFs onSuccess with apiData.global_field.uid', async () => { - importGlobalFields['existingGFs'] = [ - { uid: 'gf1', global_field: { uid: 'gf1' } } - ]; + importGlobalFields['existingGFs'] = [{ uid: 'gf1', global_field: { uid: 'gf1' } }]; await importGlobalFields.replaceGFs(); - const onSuccess = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0].apiParams.resolve; + const onSuccess = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0].apiParams.resolve; const mockGF = { uid: 'gf1', title: 'GF 1' }; onSuccess({ response: mockGF, apiData: { global_field: { uid: 'gf1' } } }); @@ -1004,15 +1019,13 @@ describe('ImportGlobalFields', () => { }); it('should handle replaceGFs onSuccess with unknown uid', async () => { - importGlobalFields['existingGFs'] = [ - { uid: 'gf1', global_field: { uid: 'gf1' } } - ]; + importGlobalFields['existingGFs'] = [{ uid: 'gf1', global_field: { uid: 'gf1' } }]; await importGlobalFields.replaceGFs(); - const onSuccess = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0].apiParams.resolve; + const onSuccess = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0].apiParams.resolve; const mockGF = { uid: 'gf1', title: 'GF 1' }; onSuccess({ response: mockGF, apiData: {} }); // No uid or global_field.uid @@ -1022,15 +1035,13 @@ describe('ImportGlobalFields', () => { }); it('should handle replaceGFs onReject with apiData.uid', async () => { - importGlobalFields['existingGFs'] = [ - { uid: 'gf1', global_field: { uid: 'gf1' } } - ]; + importGlobalFields['existingGFs'] = [{ uid: 'gf1', global_field: { uid: 'gf1' } }]; await importGlobalFields.replaceGFs(); - const onReject = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0].apiParams.reject; + const onReject = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0].apiParams.reject; onReject({ error: { message: 'Replace failed' }, apiData: { uid: 'gf1' } }); @@ -1039,15 +1050,13 @@ describe('ImportGlobalFields', () => { }); it('should handle replaceGFs onReject with apiData.global_field.uid', async () => { - importGlobalFields['existingGFs'] = [ - { uid: 'gf1', global_field: { uid: 'gf1' } } - ]; + importGlobalFields['existingGFs'] = [{ uid: 'gf1', global_field: { uid: 'gf1' } }]; await importGlobalFields.replaceGFs(); - const onReject = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0].apiParams.reject; + const onReject = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0].apiParams.reject; onReject({ error: { message: 'Replace failed' }, apiData: { global_field: { uid: 'gf1' } } }); @@ -1056,15 +1065,13 @@ describe('ImportGlobalFields', () => { }); it('should handle replaceGFs onReject with unknown uid', async () => { - importGlobalFields['existingGFs'] = [ - { uid: 'gf1', global_field: { uid: 'gf1' } } - ]; + importGlobalFields['existingGFs'] = [{ uid: 'gf1', global_field: { uid: 'gf1' } }]; await importGlobalFields.replaceGFs(); - const onReject = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0].apiParams.reject; + const onReject = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0].apiParams.reject; onReject({ error: { message: 'Replace failed' }, apiData: {} }); // No uid or global_field.uid @@ -1074,7 +1081,7 @@ describe('ImportGlobalFields', () => { it('should handle serializeReplaceGFs with global_field.uid', () => { const apiOptions = { - apiData: { global_field: { uid: 'gf1' }, title: 'GF 1' } + apiData: { global_field: { uid: 'gf1' }, title: 'GF 1' }, }; const result = importGlobalFields.serializeReplaceGFs(apiOptions as any); @@ -1084,7 +1091,7 @@ describe('ImportGlobalFields', () => { it('should handle serializeReplaceGFs with unknown uid', () => { const apiOptions = { - apiData: { title: 'GF 1' } // No uid or global_field.uid + apiData: { title: 'GF 1' }, // No uid or global_field.uid }; const result = importGlobalFields.serializeReplaceGFs(apiOptions as any); @@ -1113,7 +1120,7 @@ describe('ImportGlobalFields', () => { const onReject = makeConcurrentCallStub.firstCall.args[0].apiParams.reject; onReject({ error: { errors: { title: 'exists' } }, - apiData: undefined // No globalField + apiData: undefined, // No globalField }); // Should not throw, just log @@ -1124,9 +1131,9 @@ describe('ImportGlobalFields', () => { await importGlobalFields.updateGFs(); - const onSuccess = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update Global Fields' - )?.args[0].apiParams.resolve; + const onSuccess = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update Global Fields')?.args[0].apiParams.resolve; expect(() => { onSuccess({ response: { uid: 'gf1' }, apiData: {} }); // No uid in apiData @@ -1138,9 +1145,9 @@ describe('ImportGlobalFields', () => { await importGlobalFields.updateGFs(); - const onReject = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Update Global Fields' - )?.args[0].apiParams.reject; + const onReject = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Update Global Fields')?.args[0].apiParams.reject; expect(() => { onReject({ error: { message: 'Update failed' }, apiData: {} }); // No uid in apiData @@ -1148,15 +1155,13 @@ describe('ImportGlobalFields', () => { }); it('should handle replaceGFs onSuccess with null apiData', async () => { - importGlobalFields['existingGFs'] = [ - { uid: 'gf1', global_field: { uid: 'gf1' } } - ]; + importGlobalFields['existingGFs'] = [{ uid: 'gf1', global_field: { uid: 'gf1' } }]; await importGlobalFields.replaceGFs(); - const onSuccess = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0].apiParams.resolve; + const onSuccess = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0].apiParams.resolve; const mockGF = { uid: 'gf1', title: 'GF 1' }; onSuccess({ response: mockGF, apiData: null }); // Null apiData @@ -1166,15 +1171,13 @@ describe('ImportGlobalFields', () => { }); it('should handle replaceGFs onReject with null apiData', async () => { - importGlobalFields['existingGFs'] = [ - { uid: 'gf1', global_field: { uid: 'gf1' } } - ]; + importGlobalFields['existingGFs'] = [{ uid: 'gf1', global_field: { uid: 'gf1' } }]; await importGlobalFields.replaceGFs(); - const onReject = makeConcurrentCallStub.getCalls().find((call: any) => - call.args[0].processName === 'Replace global fields' - )?.args[0].apiParams.reject; + const onReject = makeConcurrentCallStub + .getCalls() + .find((call: any) => call.args[0].processName === 'Replace global fields')?.args[0].apiParams.reject; onReject({ error: { message: 'Replace failed' }, apiData: null }); // Null apiData @@ -1182,15 +1185,14 @@ describe('ImportGlobalFields', () => { expect(importGlobalFields['failedGFs'][0].uid).to.equal('unknown'); }); - it('should handle null UID mapper file', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; fileHelperStub.fileExistsSync.withArgs(sinon.match(/uid-mapping\.json/)).returns(true); fileHelperStub.fileExistsSync.returns(false); @@ -1198,16 +1200,18 @@ describe('ImportGlobalFields', () => { fsUtilStub.readFile.withArgs(sinon.match(/uid-mapping\.json/)).returns(null); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'seedGFs').resolves(); @@ -1223,12 +1227,12 @@ describe('ImportGlobalFields', () => { it('should not replace when replaceExisting is false', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; importGlobalFields['importConfig'].replaceExisting = false; importGlobalFields['existingGFs'] = [{ uid: 'gf1', global_field: { uid: 'gf1' } }]; @@ -1236,16 +1240,18 @@ describe('ImportGlobalFields', () => { fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -1263,12 +1269,12 @@ describe('ImportGlobalFields', () => { it('should not replace when existingGFs is empty', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; importGlobalFields['importConfig'].replaceExisting = true; importGlobalFields['existingGFs'] = []; @@ -1276,16 +1282,18 @@ describe('ImportGlobalFields', () => { fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -1303,28 +1311,30 @@ describe('ImportGlobalFields', () => { it('should not write pending file when array is empty', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); importGlobalFields['pendingGFs'] = []; - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -1340,28 +1350,30 @@ describe('ImportGlobalFields', () => { it('should not write success file when array is empty', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); importGlobalFields['createdGFs'] = []; - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -1377,28 +1389,30 @@ describe('ImportGlobalFields', () => { it('should not write fails file when array is empty', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); importGlobalFields['failedGFs'] = []; - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -1420,23 +1434,27 @@ describe('ImportGlobalFields', () => { sinon.stub(fsUtil, 'writeFile'); sinon.stub(fsUtil, 'makeDirectory'); sinon.stub(fileHelper, 'fileExistsSync'); - - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([2]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); const seedGFsStub = sinon.stub(importGlobalFields as any, 'seedGFs').resolves(); const updateGFsStub = sinon.stub(importGlobalFields as any, 'updateGFs').resolves(); - const processGlobalFieldResultsStub = sinon.stub(importGlobalFields as any, 'processGlobalFieldResults').resolves(); + const processGlobalFieldResultsStub = sinon + .stub(importGlobalFields as any, 'processGlobalFieldResults') + .resolves(); sinon.stub(importGlobalFields as any, 'completeProgress').resolves(); await importGlobalFields.start(); @@ -1448,28 +1466,30 @@ describe('ImportGlobalFields', () => { it('should handle complete flow with replaceExisting', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; importGlobalFields['importConfig'].replaceExisting = true; fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -1491,27 +1511,29 @@ describe('ImportGlobalFields', () => { it('should handle complete flow with pending and failed global fields', async () => { sinon.restore(); - + sinon.stub(fsUtil, 'readFile').callsFake(fsUtilStub.readFile); sinon.stub(fsUtil, 'writeFile').callsFake(fsUtilStub.writeFile); sinon.stub(fsUtil, 'makeDirectory').callsFake(fsUtilStub.makeDirectory); sinon.stub(fileHelper, 'fileExistsSync').callsFake(fileHelperStub.fileExistsSync); - + const mockGFs = [{ uid: 'gf1', title: 'GF 1', schema: [] as any }]; fsUtilStub.readFile.withArgs(sinon.match(/globalfields\.json/)).returns(mockGFs); fsUtilStub.readFile.withArgs(sinon.match(/marketplace_apps.*uid-mapping\.json/)).returns({ extension_uid: {} }); - sinon.stub(importGlobalFields as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importGlobalFields as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importGlobalFields as any, 'analyzeGlobalFields').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importGlobalFields as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importGlobalFields as any, 'prepareGlobalFieldMapper').resolves(); @@ -1530,4 +1552,3 @@ describe('ImportGlobalFields', () => { }); }); }); - diff --git a/packages/contentstack-import/test/unit/import/modules/locales.test.ts b/packages/contentstack-import/test/unit/import/modules/locales.test.ts index 6957d528bd..69d4ca60ad 100644 --- a/packages/contentstack-import/test/unit/import/modules/locales.test.ts +++ b/packages/contentstack-import/test/unit/import/modules/locales.test.ts @@ -167,7 +167,6 @@ describe('ImportLocales', () => { marketplaceAppEncryptionKey: 'test-key', getEncryptionKeyMaxRetry: 3, overwriteSupportedModules: [], - onlyTSModules: [], globalModules: [], entriesPublish: false, cliLogsPath: '/test/logs', @@ -176,7 +175,6 @@ describe('ImportLocales', () => { skipPrivateAppRecreationIfExist: false, master_locale: { code: 'en-us' }, masterLocale: { code: 'en-us' }, - contentVersion: 1, region: 'us' as any, 'exclude-global-modules': false, context: { @@ -257,9 +255,11 @@ describe('ImportLocales', () => { fsUtilStub.returns([]); fileHelperStub.resolves(); - sandbox.stub(localesInstance as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sandbox + .stub(localesInstance as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); const result = await localesInstance.start(); @@ -271,9 +271,11 @@ describe('ImportLocales', () => { fsUtilStub.returns(null); fileHelperStub.resolves(); - sandbox.stub(localesInstance as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sandbox + .stub(localesInstance as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); const result = await localesInstance.start(); @@ -297,15 +299,17 @@ describe('ImportLocales', () => { fileHelperStub.resolves(); makeConcurrentCallStub.resolves(); - sandbox.stub(localesInstance as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sandbox + .stub(localesInstance as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); const mockProgress = { addProcess: sandbox.stub(), startProcess: sandbox.stub().returns({ updateStatus: sandbox.stub() }), completeProcess: sandbox.stub(), updateStatus: sandbox.stub(), - tick: sandbox.stub() + tick: sandbox.stub(), }; sandbox.stub(localesInstance as any, 'setupLocalesProgress').returns(mockProgress); sandbox.stub(localesInstance as any, 'prepareLocalesMapper').resolves(); @@ -344,7 +348,7 @@ describe('ImportLocales', () => { startProcess: sandbox.stub().returns({ updateStatus: sandbox.stub() }), completeProcess: sandbox.stub(), updateStatus: sandbox.stub(), - tick: sandbox.stub() + tick: sandbox.stub(), }; sandbox.stub(localesInstance as any, 'setupLocalesProgress').returns(mockProgress); sandbox.stub(localesInstance as any, 'prepareLocalesMapper').resolves(); @@ -379,15 +383,17 @@ describe('ImportLocales', () => { const fileExistsSyncStub = sandbox.stub(require('../../../../src/utils').fileHelper, 'fileExistsSync'); fileExistsSyncStub.returns(true); - sandbox.stub(localesInstance as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sandbox + .stub(localesInstance as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); const mockProgress = { addProcess: sandbox.stub(), startProcess: sandbox.stub().returns({ updateStatus: sandbox.stub() }), completeProcess: sandbox.stub(), updateStatus: sandbox.stub(), - tick: sandbox.stub() + tick: sandbox.stub(), }; sandbox.stub(localesInstance as any, 'setupLocalesProgress').returns(mockProgress); sandbox.stub(localesInstance as any, 'prepareLocalesMapper').resolves(); @@ -410,15 +416,17 @@ describe('ImportLocales', () => { fsUtilStub.onFirstCall().returns(mockLanguages).onSecondCall().returns({}).onThirdCall().returns({}); fileHelperStub.resolves(); - sandbox.stub(localesInstance as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sandbox + .stub(localesInstance as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); const mockProgress = { addProcess: sandbox.stub(), startProcess: sandbox.stub().returns({ updateStatus: sandbox.stub() }), completeProcess: sandbox.stub(), updateStatus: sandbox.stub(), - tick: sandbox.stub() + tick: sandbox.stub(), }; sandbox.stub(localesInstance as any, 'setupLocalesProgress').returns(mockProgress); sandbox.stub(localesInstance as any, 'prepareLocalesMapper').resolves(); @@ -445,15 +453,17 @@ describe('ImportLocales', () => { fileHelperStub.resolves(); makeConcurrentCallStub.rejects(new Error('Create locales error')); - sandbox.stub(localesInstance as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sandbox + .stub(localesInstance as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); const mockProgress = { addProcess: sandbox.stub(), startProcess: sandbox.stub().returns({ updateStatus: sandbox.stub() }), completeProcess: sandbox.stub(), updateStatus: sandbox.stub(), - tick: sandbox.stub() + tick: sandbox.stub(), }; sandbox.stub(localesInstance as any, 'setupLocalesProgress').returns(mockProgress); sandbox.stub(localesInstance as any, 'prepareLocalesMapper').resolves(); @@ -472,15 +482,17 @@ describe('ImportLocales', () => { fileHelperStub.resolves(); makeConcurrentCallStub.onFirstCall().resolves().onSecondCall().rejects(new Error('Update locales error')); - sandbox.stub(localesInstance as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sandbox + .stub(localesInstance as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); const mockProgress = { addProcess: sandbox.stub(), startProcess: sandbox.stub().returns({ updateStatus: sandbox.stub() }), completeProcess: sandbox.stub(), updateStatus: sandbox.stub(), - tick: sandbox.stub() + tick: sandbox.stub(), }; sandbox.stub(localesInstance as any, 'setupLocalesProgress').returns(mockProgress); sandbox.stub(localesInstance as any, 'prepareLocalesMapper').resolves(); diff --git a/packages/contentstack-import/test/unit/import/modules/personalize.test.ts b/packages/contentstack-import/test/unit/import/modules/personalize.test.ts index fd90b32e20..e8c239493e 100644 --- a/packages/contentstack-import/test/unit/import/modules/personalize.test.ts +++ b/packages/contentstack-import/test/unit/import/modules/personalize.test.ts @@ -8,16 +8,16 @@ const mockImport = { Events: sinon.stub(), Audiences: sinon.stub(), Attribute: sinon.stub(), - Experiences: sinon.stub() + Experiences: sinon.stub(), }; const mockVariantsModule = { - Import: mockImport + Import: mockImport, }; const Module = require('node:module'); const originalRequire = Module.prototype.require; -Module.prototype.require = function(id: string) { +Module.prototype.require = function (id: string) { if (id === '@contentstack/cli-variants') { return mockVariantsModule; } @@ -37,20 +37,20 @@ describe('ImportPersonalize', () => { beforeEach(() => { mockStackClient = { stack: sinon.stub().returns({ - apiKey: 'test' - }) + apiKey: 'test', + }), }; logStub = { debug: sinon.stub(), info: sinon.stub(), - success: sinon.stub() + success: sinon.stub(), }; - + Object.assign(log, { debug: logStub.debug, info: logStub.info, - success: logStub.success + success: logStub.success, }); handleAndLogErrorStub = sinon.stub(); @@ -60,12 +60,11 @@ describe('ImportPersonalize', () => { apiKey: 'test', backupDir: '/test/backup', data: '/test/content', - contentVersion: 1, region: { name: 'NA', cma: 'https://api.contentstack.io', cda: 'https://cdn.contentstack.io', - uiHost: 'https://app.contentstack.com' + uiHost: 'https://app.contentstack.com', }, context: { command: 'cm:stacks:import', @@ -75,14 +74,14 @@ describe('ImportPersonalize', () => { sessionId: 'session-123', apiKey: 'test', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, modules: { personalize: { baseURL: { - 'NA': 'https://personalize-na.contentstack.com', - 'EU': 'https://personalize-eu.contentstack.com', - 'Azure-NA': 'https://personalize-azure-na.contentstack.com' + NA: 'https://personalize-na.contentstack.com', + EU: 'https://personalize-eu.contentstack.com', + 'Azure-NA': 'https://personalize-azure-na.contentstack.com', }, dirName: 'personalize', importData: true, @@ -90,28 +89,28 @@ describe('ImportPersonalize', () => { project_id: 'test-project-id', projects: { dirName: 'projects', - fileName: 'projects.json' + fileName: 'projects.json', }, attributes: { dirName: 'attributes', - fileName: 'attributes.json' + fileName: 'attributes.json', }, audiences: { dirName: 'audiences', - fileName: 'audiences.json' + fileName: 'audiences.json', }, events: { dirName: 'events', - fileName: 'events.json' + fileName: 'events.json', }, experiences: { dirName: 'experiences', fileName: 'experiences.json', thresholdTimer: 1000, - checkIntervalDuration: 500 - } - } - } + checkIntervalDuration: 500, + }, + }, + }, } as any; // Reset all mocks @@ -130,24 +129,24 @@ describe('ImportPersonalize', () => { describe('Constructor', () => { it('should initialize with correct parameters', () => { - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); - + expect(importPersonalize).to.be.instanceOf(ImportPersonalize); expect(importPersonalize['config']).to.equal(mockImportConfig); expect(importPersonalize['personalizeConfig']).to.equal(mockImportConfig.modules.personalize); }); it('should set context module to personalize', () => { - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); - + expect(importPersonalize['config'].context.module).to.equal('personalize'); }); }); @@ -155,10 +154,10 @@ describe('ImportPersonalize', () => { describe('start() - Early Return Scenarios', () => { it('should return early when no baseURL found for region', async () => { mockImportConfig.region.name = 'INVALID_REGION'; - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -169,10 +168,10 @@ describe('ImportPersonalize', () => { it('should return early when management token is present', async () => { mockImportConfig.management_token = 'test-management-token'; - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -183,10 +182,10 @@ describe('ImportPersonalize', () => { it('should check baseURL before management token', async () => { mockImportConfig.region.name = 'INVALID_REGION'; mockImportConfig.management_token = 'test-management-token'; - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -201,34 +200,36 @@ describe('ImportPersonalize', () => { beforeEach(() => { mockImport.Project.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Events.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Audiences.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Attribute.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Experiences.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() - }); - - sinon.stub(ImportPersonalize.prototype as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); + setParentProgressManager: sinon.stub(), }); + + sinon + .stub(ImportPersonalize.prototype as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(ImportPersonalize.prototype as any, 'createNestedProgress').returns(mockProgress); sinon.stub(ImportPersonalize.prototype as any, 'analyzePersonalize').resolves([true, 4]); // 4 modules @@ -238,13 +239,13 @@ describe('ImportPersonalize', () => { mockImportConfig.modules.personalize.importData = false; mockImport.Project.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); - - importPersonalize = new ImportPersonalize({ + + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); const importProjectsStub = sinon.stub(importPersonalize as any, 'importProjects').resolves(); @@ -258,25 +259,25 @@ describe('ImportPersonalize', () => { it('should successfully import project with importData = true and process all modules', async () => { mockImport.Events.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Audiences.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Attribute.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Experiences.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); - - importPersonalize = new ImportPersonalize({ + + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -291,12 +292,12 @@ describe('ImportPersonalize', () => { it('should handle project import failure', async () => { const projectError = new Error('Project import failed'); mockImport.Project.returns({ - import: sinon.stub().rejects(projectError) + import: sinon.stub().rejects(projectError), }); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); const importProjectsStub = sinon.stub(importPersonalize as any, 'importProjects').rejects(projectError); @@ -315,17 +316,17 @@ describe('ImportPersonalize', () => { mockImportConfig.modules.personalize.importOrder = ['audiences', 'events']; mockImport.Audiences.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Events.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); - - importPersonalize = new ImportPersonalize({ + + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -341,18 +342,20 @@ describe('ImportPersonalize', () => { beforeEach(() => { mockImport.Project.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() - }); - - sinon.stub(ImportPersonalize.prototype as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); + setParentProgressManager: sinon.stub(), }); + + sinon + .stub(ImportPersonalize.prototype as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(ImportPersonalize.prototype as any, 'createNestedProgress').returns(mockProgress); sinon.stub(ImportPersonalize.prototype as any, 'analyzePersonalize').resolves([true, 4]); // 4 modules @@ -363,25 +366,25 @@ describe('ImportPersonalize', () => { it('should process all valid modules in correct order', async () => { mockImport.Events.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Audiences.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Attribute.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Experiences.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -408,32 +411,34 @@ describe('ImportPersonalize', () => { mockImportConfig.modules.personalize.importOrder = ['events', 'invalidModule', 'audiences']; mockImport.Events.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Audiences.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); sinon.restore(); - sinon.stub(ImportPersonalize.prototype as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(ImportPersonalize.prototype as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(ImportPersonalize.prototype as any, 'createNestedProgress').returns(mockProgress); sinon.stub(ImportPersonalize.prototype as any, 'analyzePersonalize').resolves([true, 2]); // 2 modules sinon.stub(ImportPersonalize.prototype as any, 'importProjects').resolves(); sinon.stub(ImportPersonalize.prototype as any, 'completeProgress').resolves(); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -449,17 +454,17 @@ describe('ImportPersonalize', () => { const moduleError = new Error('Module import failed'); mockImport.Events.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Audiences.returns({ import: sinon.stub().rejects(moduleError), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -470,10 +475,10 @@ describe('ImportPersonalize', () => { it('should handle empty importOrder array', async () => { mockImportConfig.modules.personalize.importOrder = []; - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -488,25 +493,25 @@ describe('ImportPersonalize', () => { it('should instantiate modules with correct config', async () => { mockImport.Events.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Audiences.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Attribute.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); mockImport.Experiences.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -529,10 +534,10 @@ describe('ImportPersonalize', () => { mockImport.Attribute.returns(attributeInstance); mockImport.Experiences.returns(experiencesInstance); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -549,13 +554,13 @@ describe('ImportPersonalize', () => { // The actual moduleMapper is created in the code, so this tests the || {} fallback mockImport.Project.returns({ import: sinon.stub().resolves(), - setParentProgressManager: sinon.stub() + setParentProgressManager: sinon.stub(), }); - - importPersonalize = new ImportPersonalize({ + + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -569,13 +574,13 @@ describe('ImportPersonalize', () => { it('should handle network error during project import', async () => { const networkError = new Error('Network connection failed'); mockImport.Project.returns({ - import: sinon.stub().rejects(networkError) + import: sinon.stub().rejects(networkError), }); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -588,13 +593,13 @@ describe('ImportPersonalize', () => { mockImportConfig.modules.personalize.importData = false; const error = new Error('Some error'); mockImport.Project.returns({ - import: sinon.stub().rejects(error) + import: sinon.stub().rejects(error), }); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -606,17 +611,17 @@ describe('ImportPersonalize', () => { it('should handle module throwing error', async () => { mockImport.Project.returns({ - import: sinon.stub().resolves() + import: sinon.stub().resolves(), }); const moduleError = new Error('Module error'); mockImport.Events.returns({ - import: sinon.stub().rejects(moduleError) + import: sinon.stub().rejects(moduleError), }); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -628,13 +633,13 @@ describe('ImportPersonalize', () => { it('should call handleAndLogError with correct context', async () => { const error = new Error('Test error'); mockImport.Project.returns({ - import: sinon.stub().rejects(error) + import: sinon.stub().rejects(error), }); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -646,13 +651,13 @@ describe('ImportPersonalize', () => { it('should handle error and check importData flag after error', async () => { const error = new Error('Test error for importData check'); mockImport.Project.returns({ - import: sinon.stub().rejects(error) + import: sinon.stub().rejects(error), }); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -666,28 +671,28 @@ describe('ImportPersonalize', () => { describe('start() - Logging and Debug Tests', () => { beforeEach(() => { mockImport.Project.returns({ - import: sinon.stub().resolves() + import: sinon.stub().resolves(), }); }); it('should log debug messages at key points', async () => { mockImport.Events.returns({ - import: sinon.stub().resolves() + import: sinon.stub().resolves(), }); mockImport.Audiences.returns({ - import: sinon.stub().resolves() + import: sinon.stub().resolves(), }); mockImport.Attribute.returns({ - import: sinon.stub().resolves() + import: sinon.stub().resolves(), }); mockImport.Experiences.returns({ - import: sinon.stub().resolves() + import: sinon.stub().resolves(), }); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -697,22 +702,22 @@ describe('ImportPersonalize', () => { it('should log success messages for each module and overall completion', async () => { mockImport.Events.returns({ - import: sinon.stub().resolves() + import: sinon.stub().resolves(), }); mockImport.Audiences.returns({ - import: sinon.stub().resolves() + import: sinon.stub().resolves(), }); mockImport.Attribute.returns({ - import: sinon.stub().resolves() + import: sinon.stub().resolves(), }); mockImport.Experiences.returns({ - import: sinon.stub().resolves() + import: sinon.stub().resolves(), }); - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -723,10 +728,10 @@ describe('ImportPersonalize', () => { it('should log info messages for skipped scenarios', async () => { // Test no baseURL scenario mockImportConfig.region.name = 'INVALID_REGION'; - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); @@ -736,10 +741,10 @@ describe('ImportPersonalize', () => { // Reset and test management token scenario mockImportConfig.region.name = 'NA'; mockImportConfig.management_token = 'test-token'; - importPersonalize = new ImportPersonalize({ + importPersonalize = new ImportPersonalize({ importConfig: mockImportConfig, stackAPIClient: mockStackClient, - moduleName: 'personalize' + moduleName: 'personalize', }); await importPersonalize.start(); diff --git a/packages/contentstack-import/test/unit/import/modules/variant-entries.test.ts b/packages/contentstack-import/test/unit/import/modules/variant-entries.test.ts index 89bcbb015c..d629b8f5c0 100644 --- a/packages/contentstack-import/test/unit/import/modules/variant-entries.test.ts +++ b/packages/contentstack-import/test/unit/import/modules/variant-entries.test.ts @@ -75,7 +75,7 @@ describe('ImportVariantEntries', () => { beforeEach(() => { mockImportConfig = { - data: '/test/backup', + contentDir: '/test/backup', apiKey: 'test-api-key', context: { command: 'cm:stacks:import', @@ -269,7 +269,7 @@ describe('ImportVariantEntries', () => { const constructorArgs = mockImport.VariantEntries.getCall(0).args[0]; // Verify original config properties are preserved - expect(constructorArgs.data).to.equal('/test/backup'); + expect(constructorArgs.contentDir).to.equal('/test/backup'); expect(constructorArgs.apiKey).to.equal('test-api-key'); expect(constructorArgs.context).to.deep.equal(mockImportConfig.context); @@ -470,7 +470,7 @@ describe('ImportVariantEntries', () => { expect(constructorArgs.helpers).to.be.an('object'); // Verify other config properties are still present - expect(constructorArgs).to.have.property('data'); + expect(constructorArgs).to.have.property('contentDir'); expect(constructorArgs).to.have.property('apiKey'); expect(constructorArgs).to.have.property('context'); }); @@ -528,7 +528,7 @@ describe('ImportVariantEntries', () => { it('should handle different data paths in projectMapperFilePath construction', () => { const customConfig = { ...mockImportConfig, - data: '/custom/backup/path' + contentDir: '/custom/backup/path' }; const customImportVariantEntries = new ImportVariantEntries({ importConfig: customConfig diff --git a/packages/contentstack-import/test/unit/import/modules/workflows.test.ts b/packages/contentstack-import/test/unit/import/modules/workflows.test.ts index 0cd273dad5..37494b7058 100644 --- a/packages/contentstack-import/test/unit/import/modules/workflows.test.ts +++ b/packages/contentstack-import/test/unit/import/modules/workflows.test.ts @@ -16,11 +16,11 @@ describe('ImportWorkflows', () => { fsUtilStub = { readFile: sinon.stub(), writeFile: sinon.stub(), - makeDirectory: sinon.stub().resolves() + makeDirectory: sinon.stub().resolves(), }; - + fileHelperStub = { - fileExistsSync: sinon.stub() + fileExistsSync: sinon.stub(), }; // Use sinon.replace to replace the entire modules @@ -30,19 +30,18 @@ describe('ImportWorkflows', () => { const mockWorkflowUpdate = sinon.stub().resolves({ uid: 'wf-123', name: 'Test WF' }); mockStackClient = { role: sinon.stub().returns({ - fetchAll: sinon.stub().resolves({ items: [{ name: 'Test Role', uid: 'role-123' }] }) + fetchAll: sinon.stub().resolves({ items: [{ name: 'Test Role', uid: 'role-123' }] }), }), workflow: sinon.stub().returns({ create: sinon.stub().resolves({ uid: 'wf-123', name: 'Test WF', workflow_stages: [] }), - update: mockWorkflowUpdate - }) + update: mockWorkflowUpdate, + }), }; mockImportConfig = { apiKey: 'test', backupDir: '/test/backup', data: '/test/content', - contentVersion: 1, region: 'us', fetchConcurrency: 2, context: { @@ -53,20 +52,20 @@ describe('ImportWorkflows', () => { sessionId: 'session-123', apiKey: 'test', orgId: 'org-123', - authenticationMethod: 'Basic Auth' + authenticationMethod: 'Basic Auth', }, modules: { workflows: { dirName: 'workflows', - fileName: 'workflows.json' - } - } + fileName: 'workflows.json', + }, + }, } as any; importWorkflows = new ImportWorkflows({ importConfig: mockImportConfig as any, stackAPIClient: mockStackClient, - moduleName: 'workflows' + moduleName: 'workflows', }); sinon.stub(importWorkflows as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { @@ -78,7 +77,7 @@ describe('ImportWorkflows', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importWorkflows as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importWorkflows as any, 'prepareWorkflowMapper').resolves(); @@ -123,14 +122,16 @@ describe('ImportWorkflows', () => { describe('start()', () => { it('should return early when workflows folder does not exist', async () => { sinon.restore(); - + sinon.replace(require('../../../../src/utils'), 'fileHelper', fileHelperStub); sinon.replaceGetter(require('../../../../src/utils'), 'fsUtil', () => fsUtilStub); - - sinon.stub(importWorkflows as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); - + + sinon + .stub(importWorkflows as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); + fileHelperStub.fileExistsSync.returns(false); await importWorkflows.start(); @@ -140,14 +141,16 @@ describe('ImportWorkflows', () => { it('should return early when workflows is empty', async () => { sinon.restore(); - + sinon.replace(require('../../../../src/utils'), 'fileHelper', fileHelperStub); sinon.replaceGetter(require('../../../../src/utils'), 'fsUtil', () => fsUtilStub); - - sinon.stub(importWorkflows as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); - + + sinon + .stub(importWorkflows as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); + fileHelperStub.fileExistsSync.returns(true); fsUtilStub.readFile.returns({}); @@ -158,13 +161,15 @@ describe('ImportWorkflows', () => { it('should process workflows when available', async () => { sinon.restore(); - + sinon.replace(require('../../../../src/utils'), 'fileHelper', fileHelperStub); sinon.replaceGetter(require('../../../../src/utils'), 'fsUtil', () => fsUtilStub); - - sinon.stub(importWorkflows as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importWorkflows as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importWorkflows as any, 'getRoles').resolves(); sinon.stub(importWorkflows as any, 'completeProgress').resolves(); const mockProgress = { @@ -172,14 +177,14 @@ describe('ImportWorkflows', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importWorkflows as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importWorkflows as any, 'processWorkflowResults').resolves(); makeConcurrentCallStub = sinon.stub(importWorkflows as any, 'makeConcurrentCall').resolves(); - + const mockWorkflows = { - wf1: { uid: 'wf1', name: 'Workflow 1', workflow_stages: [] as any } + wf1: { uid: 'wf1', name: 'Workflow 1', workflow_stages: [] as any }, }; fileHelperStub.fileExistsSync.withArgs(sinon.match(/workflows$/)).returns(true); @@ -193,13 +198,15 @@ describe('ImportWorkflows', () => { it('should load existing UID mapper when file exists', async () => { sinon.restore(); - + sinon.replace(require('../../../../src/utils'), 'fileHelper', fileHelperStub); sinon.replaceGetter(require('../../../../src/utils'), 'fsUtil', () => fsUtilStub); - - sinon.stub(importWorkflows as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importWorkflows as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importWorkflows as any, 'getRoles').resolves(); sinon.stub(importWorkflows as any, 'completeProgress').resolves(); const mockProgress = { @@ -207,12 +214,12 @@ describe('ImportWorkflows', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importWorkflows as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importWorkflows as any, 'processWorkflowResults').resolves(); makeConcurrentCallStub = sinon.stub(importWorkflows as any, 'makeConcurrentCall').resolves(); - + const mockWorkflows = { wf1: { uid: 'wf1', name: 'WF 1', workflow_stages: [] as any } }; const mockUidMapper = { wf1: 'mapped-wf1' }; @@ -228,13 +235,15 @@ describe('ImportWorkflows', () => { it('should write success file when workflows created', async () => { sinon.restore(); - + sinon.replace(require('../../../../src/utils'), 'fileHelper', fileHelperStub); sinon.replaceGetter(require('../../../../src/utils'), 'fsUtil', () => fsUtilStub); - - sinon.stub(importWorkflows as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importWorkflows as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importWorkflows as any, 'getRoles').resolves(); sinon.stub(importWorkflows as any, 'completeProgress').resolves(); const mockProgress = { @@ -242,11 +251,11 @@ describe('ImportWorkflows', () => { startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importWorkflows as any, 'createNestedProgress').returns(mockProgress); makeConcurrentCallStub = sinon.stub(importWorkflows as any, 'makeConcurrentCall').resolves(); - + const mockWorkflows = { wf1: { uid: 'wf1', name: 'WF 1', workflow_stages: [] as any } }; fileHelperStub.fileExistsSync.withArgs(sinon.match(/workflows$/)).returns(true); @@ -264,16 +273,18 @@ describe('ImportWorkflows', () => { const mockWorkflows = { wf1: { uid: 'wf1', name: 'WF 1', workflow_stages: [] as any } }; sinon.restore(); - sinon.stub(importWorkflows as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + sinon + .stub(importWorkflows as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importWorkflows as any, 'analyzeWorkflows').resolves([1]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importWorkflows as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importWorkflows as any, 'prepareWorkflowMapper').resolves(); @@ -288,7 +299,7 @@ describe('ImportWorkflows', () => { importWorkflows['failedWebhooks'] = [{ uid: 'wf1' }]; const processWorkflowResultsStub = sinon.stub(importWorkflows as any, 'processWorkflowResults'); - + await importWorkflows.start(); expect(processWorkflowResultsStub.called).to.be.true; @@ -303,24 +314,24 @@ describe('ImportWorkflows', () => { const mockRoles = [ { name: 'Role 1', uid: 'role1' }, - { name: 'Role 2', uid: 'role2' } + { name: 'Role 2', uid: 'role2' }, ]; mockStackClient.role.returns({ - fetchAll: sinon.stub().resolves({ items: mockRoles }) + fetchAll: sinon.stub().resolves({ items: mockRoles }), }); await importWorkflows.getRoles(); expect(importWorkflows['roleNameMap']).to.deep.equal({ 'Role 1': 'role1', - 'Role 2': 'role2' + 'Role 2': 'role2', }); }); it('should handle role fetch error', async () => { mockStackClient.role.returns({ - fetchAll: sinon.stub().rejects(new Error('Fetch failed')) + fetchAll: sinon.stub().rejects(new Error('Fetch failed')), }); await importWorkflows.getRoles(); @@ -330,7 +341,7 @@ describe('ImportWorkflows', () => { it('should handle empty roles response', async () => { mockStackClient.role.returns({ - fetchAll: sinon.stub().resolves({ items: [] }) + fetchAll: sinon.stub().resolves({ items: [] }), }); await importWorkflows.getRoles(); @@ -342,7 +353,7 @@ describe('ImportWorkflows', () => { describe('importWorkflows()', () => { beforeEach(() => { importWorkflows['workflows'] = { - wf1: { uid: 'wf1', name: 'Workflow 1', workflow_stages: [] as any } + wf1: { uid: 'wf1', name: 'Workflow 1', workflow_stages: [] as any }, }; }); @@ -372,7 +383,7 @@ describe('ImportWorkflows', () => { const onReject = makeConcurrentCallStub.firstCall.args[0].apiParams.reject; onReject({ error: { message: JSON.stringify({ errors: { name: 'exists' } }) }, - apiData: { name: 'Workflow 1', uid: 'wf1' } + apiData: { name: 'Workflow 1', uid: 'wf1' }, }); expect(importWorkflows['failedWebhooks']).to.have.lengthOf(0); @@ -384,7 +395,7 @@ describe('ImportWorkflows', () => { const onReject = makeConcurrentCallStub.firstCall.args[0].apiParams.reject; onReject({ error: { errors: { 'workflow_stages.0.users': 'error' } }, - apiData: { name: 'Workflow 1', uid: 'wf1' } + apiData: { name: 'Workflow 1', uid: 'wf1' }, }); expect(importWorkflows['failedWebhooks']).to.have.lengthOf(1); @@ -396,7 +407,7 @@ describe('ImportWorkflows', () => { const onReject = makeConcurrentCallStub.firstCall.args[0].apiParams.reject; onReject({ error: { message: JSON.stringify({ errorCode: 500 }) }, - apiData: { name: 'Workflow 1', uid: 'wf1' } + apiData: { name: 'Workflow 1', uid: 'wf1' }, }); expect(importWorkflows['failedWebhooks']).to.have.lengthOf(1); @@ -406,9 +417,7 @@ describe('ImportWorkflows', () => { const mockWorkflow = { uid: 'wf1', name: 'WF 1', - workflow_stages: [ - { uid: 'stage1', name: 'Stage 1', next_available_stages: ['stage2'] } - ] + workflow_stages: [{ uid: 'stage1', name: 'Stage 1', next_available_stages: ['stage2'] }], }; importWorkflows['workflows'] = { wf1: mockWorkflow }; @@ -418,7 +427,7 @@ describe('ImportWorkflows', () => { const response = { uid: 'wf-new', name: 'WF 1', - workflow_stages: [{ uid: 'new-stage1', name: 'Stage 1' }] + workflow_stages: [{ uid: 'new-stage1', name: 'Stage 1' }], }; await onSuccess({ response, apiData: { uid: 'wf1', name: 'WF 1' } }); @@ -432,7 +441,7 @@ describe('ImportWorkflows', () => { importWorkflows['workflowUidMapper'] = { wf1: 'mapped-wf1' }; const apiOptions = { apiData: { uid: 'wf1', name: 'Workflow 1', workflow_stages: [] as any }, - entity: 'create-workflows' + entity: 'create-workflows', }; const result = importWorkflows.serializeWorkflows(apiOptions as any); @@ -446,8 +455,8 @@ describe('ImportWorkflows', () => { uid: 'wf1', name: 'Workflow 1', admin_users: ['user1'], - workflow_stages: [] as any - } + workflow_stages: [] as any, + }, }; const result = importWorkflows.serializeWorkflows(apiOptions as any); @@ -457,7 +466,7 @@ describe('ImportWorkflows', () => { it('should add default branches if not present', () => { const apiOptions = { - apiData: { uid: 'wf1', name: 'Workflow 1', workflow_stages: [] as any } + apiData: { uid: 'wf1', name: 'Workflow 1', workflow_stages: [] as any }, }; const result = importWorkflows.serializeWorkflows(apiOptions as any); @@ -471,8 +480,8 @@ describe('ImportWorkflows', () => { uid: 'wf1', name: 'Workflow 1', branches: ['custom-branch'], - workflow_stages: [] as any - } + workflow_stages: [] as any, + }, }; const result = importWorkflows.serializeWorkflows(apiOptions as any); @@ -485,10 +494,8 @@ describe('ImportWorkflows', () => { apiData: { uid: 'wf1', name: 'Workflow 1', - workflow_stages: [ - { uid: 'stage1', name: 'Stage 1', next_available_stages: ['stage2'] } - ] as any - } + workflow_stages: [{ uid: 'stage1', name: 'Stage 1', next_available_stages: ['stage2'] }] as any, + }, }; const result = importWorkflows.serializeWorkflows(apiOptions as any); @@ -502,8 +509,8 @@ describe('ImportWorkflows', () => { apiData: { uid: 'wf1', name: 'Workflow 1', - workflow_stages: [{ uid: 'stage1', name: 'Stage 1', next_available_stages: [] }] as any - } + workflow_stages: [{ uid: 'stage1', name: 'Stage 1', next_available_stages: [] }] as any, + }, }; const result = importWorkflows.serializeWorkflows(apiOptions as any); @@ -517,11 +524,11 @@ describe('ImportWorkflows', () => { const workflow = { uid: 'wf1', name: 'WF 1' }; const newStages = [ { uid: 'new-stage1', name: 'Stage 1' }, - { uid: 'new-stage2', name: 'Stage 2' } + { uid: 'new-stage2', name: 'Stage 2' }, ]; const oldStages = [ { uid: 'old-stage1', name: 'Stage 1', next_available_stages: ['old-stage2'] as any }, - { uid: 'old-stage2', name: 'Stage 2', next_available_stages: [] as any } + { uid: 'old-stage2', name: 'Stage 2', next_available_stages: [] as any }, ]; const result = importWorkflows.updateNextAvailableStagesUid(workflow, newStages, oldStages); @@ -560,10 +567,10 @@ describe('ImportWorkflows', () => { { SYS_ACL: { users: { uids: ['user1'] as any }, - roles: { uids: [{ uid: 'role1', name: 'Role 1', rules: [] as any }] } - } - } - ] + roles: { uids: [{ uid: 'role1', name: 'Role 1', rules: [] as any }] }, + }, + }, + ], }; await importWorkflows.createCustomRoleIfNotExists(workflow); @@ -579,10 +586,10 @@ describe('ImportWorkflows', () => { { SYS_ACL: { users: { uids: ['user1', 'user2'] as any }, - roles: { uids: [] as any } - } - } - ] + roles: { uids: [] as any }, + }, + }, + ], }; await importWorkflows.createCustomRoleIfNotExists(workflow); @@ -598,10 +605,10 @@ describe('ImportWorkflows', () => { { SYS_ACL: { users: { uids: ['$all'] as any }, - roles: { uids: [] as any } - } - } - ] + roles: { uids: [] as any }, + }, + }, + ], }; await importWorkflows.createCustomRoleIfNotExists(workflow); @@ -614,7 +621,7 @@ describe('ImportWorkflows', () => { it('should add branch rule if not exists', () => { const apiOptions = { apiData: { name: 'Role 1', rules: [] as any }, - additionalInfo: { workflowUid: 'wf1', stageIndex: 0 } + additionalInfo: { workflowUid: 'wf1', stageIndex: 0 }, }; importWorkflows['roleNameMap'] = {}; @@ -628,9 +635,9 @@ describe('ImportWorkflows', () => { const apiOptions = { apiData: { name: 'Role 1', - rules: [{ module: 'branch', branches: ['main'], acl: { read: true } }] as any + rules: [{ module: 'branch', branches: ['main'], acl: { read: true } }] as any, }, - additionalInfo: { workflowUid: 'wf1', stageIndex: 0 } + additionalInfo: { workflowUid: 'wf1', stageIndex: 0 }, }; importWorkflows['roleNameMap'] = {}; @@ -643,13 +650,13 @@ describe('ImportWorkflows', () => { importWorkflows['roleNameMap'] = { 'Role 1': 'role-123' }; importWorkflows['workflows'] = { wf1: { - workflow_stages: [{ SYS_ACL: { roles: { uids: [{ uid: 'old-role', name: 'Role 1' }] } } }] - } + workflow_stages: [{ SYS_ACL: { roles: { uids: [{ uid: 'old-role', name: 'Role 1' }] } } }], + }, }; const apiOptions = { apiData: { uid: 'old-role', name: 'Role 1', rules: [] as any }, additionalInfo: { workflowUid: 'wf1', stageIndex: 0 }, - entity: 'create-custom-role' + entity: 'create-custom-role', }; const result = importWorkflows.serializeCustomRoles(apiOptions as any); @@ -662,15 +669,15 @@ describe('ImportWorkflows', () => { it('should update role UID in workflow stage', () => { importWorkflows['workflows'] = { wf1: { - workflow_stages: [{ SYS_ACL: { roles: { uids: [{ uid: 'old-role', name: 'Role 1' }] } } }] - } + workflow_stages: [{ SYS_ACL: { roles: { uids: [{ uid: 'old-role', name: 'Role 1' }] } } }], + }, }; importWorkflows['roleNameMap'] = { 'Role 1': 'new-role' }; importWorkflows.updateRoleData({ workflowUid: 'wf1', stageIndex: 0, - roleData: { uid: 'old-role', name: 'Role 1' } + roleData: { uid: 'old-role', name: 'Role 1' }, }); expect(importWorkflows['workflows']['wf1'].workflow_stages[0].SYS_ACL.roles.uids[0]).to.equal('new-role'); @@ -679,15 +686,15 @@ describe('ImportWorkflows', () => { it('should append role if not found in existing list', () => { importWorkflows['workflows'] = { wf1: { - workflow_stages: [{ SYS_ACL: { roles: { uids: [] } } }] - } + workflow_stages: [{ SYS_ACL: { roles: { uids: [] } } }], + }, }; importWorkflows['roleNameMap'] = { 'Role 1': 'new-role' }; importWorkflows.updateRoleData({ workflowUid: 'wf1', stageIndex: 0, - roleData: { uid: 'old-role', name: 'Role 1' } + roleData: { uid: 'old-role', name: 'Role 1' }, }); expect(importWorkflows['workflows']['wf1'].workflow_stages[0].SYS_ACL.roles.uids).to.include('new-role'); @@ -730,17 +737,19 @@ describe('ImportWorkflows', () => { sinon.restore(); sinon.replace(require('../../../../src/utils'), 'fileHelper', fileHelperStub); sinon.replaceGetter(require('../../../../src/utils'), 'fsUtil', () => fsUtilStub); - - sinon.stub(importWorkflows as any, 'withLoadingSpinner').callsFake(async (msg: string, fn: () => Promise) => { - return await fn(); - }); + + sinon + .stub(importWorkflows as any, 'withLoadingSpinner') + .callsFake(async (msg: string, fn: () => Promise) => { + return await fn(); + }); sinon.stub(importWorkflows as any, 'analyzeWorkflows').resolves([2]); const mockProgress = { addProcess: sinon.stub(), startProcess: sinon.stub().returns({ updateStatus: sinon.stub() }), completeProcess: sinon.stub(), updateStatus: sinon.stub(), - tick: sinon.stub() + tick: sinon.stub(), }; sinon.stub(importWorkflows as any, 'createNestedProgress').returns(mockProgress); sinon.stub(importWorkflows as any, 'prepareWorkflowMapper').resolves(); @@ -752,7 +761,7 @@ describe('ImportWorkflows', () => { const mockWorkflows = { wf1: { uid: 'wf1', name: 'Workflow 1', workflow_stages: [] as any }, - wf2: { uid: 'wf2', name: 'Workflow 2', workflow_stages: [] as any } + wf2: { uid: 'wf2', name: 'Workflow 2', workflow_stages: [] as any }, }; fileHelperStub.fileExistsSync.withArgs(sinon.match(/workflows$/)).returns(true); @@ -765,7 +774,7 @@ describe('ImportWorkflows', () => { const importWorkflowsStub = sinon.stub(importWorkflows as any, 'importWorkflows').resolves(); const processWorkflowResultsStub = sinon.stub(importWorkflows as any, 'processWorkflowResults').resolves(); - + await importWorkflows.start(); expect(importWorkflowsStub.called).to.be.true; @@ -773,4 +782,3 @@ describe('ImportWorkflows', () => { }); }); }); - diff --git a/packages/contentstack-import/test/unit/utils/backup-handler.test.ts b/packages/contentstack-import/test/unit/utils/backup-handler.test.ts index 252a53bb24..ffb5964276 100644 --- a/packages/contentstack-import/test/unit/utils/backup-handler.test.ts +++ b/packages/contentstack-import/test/unit/utils/backup-handler.test.ts @@ -21,18 +21,18 @@ describe('Backup Handler', () => { beforeEach(() => { // Store original working directory originalCwd = process.cwd(); - + // Create temp directory - os.tmpdir() works in both local and CI environments (e.g., /tmp on Linux) // This ensures backups are created in isolated temp space, not in the working directory // In CI, os.tmpdir() returns a safe temp directory that's cleaned up automatically tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'backup-handler-test-')); sourceDir = path.join(tempDir, 'source'); backupDir = path.join(tempDir, 'backup'); - + // Stub process.cwd() to return tempDir so backups are created there, not in actual working directory // This is critical for CI - prevents creating files in the workspace during tests processCwdStub = sinon.stub(process, 'cwd').returns(tempDir); - + // Create source directory with some files fs.mkdirSync(sourceDir); fs.writeFileSync(path.join(sourceDir, 'test.json'), JSON.stringify({ key: 'value' })); @@ -46,7 +46,6 @@ describe('Backup Handler', () => { command: 'cm:stacks:import', module: 'all', }, - contentVersion: 1, masterLocale: { code: 'en-us' }, backupDir: backupDir, region: 'us', @@ -73,10 +72,10 @@ describe('Backup Handler', () => { if (processCwdStub) { processCwdStub.restore(); } - + // Restore all stubs sinon.restore(); - + // Clean up temp directory (which includes any backup dirs created in it) // This is critical for CI - must clean up temp files try { @@ -87,7 +86,7 @@ describe('Backup Handler', () => { // Ignore cleanup errors - temp dirs will be cleaned by OS console.warn(`Failed to clean temp dir ${tempDir}:`, error); } - + // Clean up any backup directories that might have been created in original working directory // This ensures CI doesn't leave files behind // Note: In CI (GitHub Actions), os.tmpdir() returns /tmp and we stub process.cwd(), diff --git a/packages/contentstack-import/test/unit/utils/common-helper.test.ts b/packages/contentstack-import/test/unit/utils/common-helper.test.ts index 274a63c57f..a53b21ba2b 100644 --- a/packages/contentstack-import/test/unit/utils/common-helper.test.ts +++ b/packages/contentstack-import/test/unit/utils/common-helper.test.ts @@ -38,7 +38,7 @@ describe('Common Helper', () => { get: sandbox.stub(), put: sandbox.stub(), }; - + const originalHttpClient = cliUtilities.HttpClient; const createStub = sandbox.stub().returns(httpClientStub); // Replace the create method on HttpClient @@ -53,7 +53,7 @@ describe('Common Helper', () => { // If replaceGetter fails, fall back to regular stub managementSDKClientStub = sandbox.stub(cliUtilities, 'managementSDKClient'); } - + // Stub fileHelper functions as they are external dependencies fileHelperStubs = { readFileSync: sandbox.stub(require('../../../src/utils/file-helper'), 'readFileSync'), @@ -61,7 +61,7 @@ describe('Common Helper', () => { readdirSync: sandbox.stub(require('../../../src/utils/file-helper'), 'readdirSync'), fileExistsSync: sandbox.stub(require('../../../src/utils/file-helper'), 'fileExistsSync'), }; - + // Don't stub isAuthenticated - let it execute naturally or use a workaround // Instead, we'll test scenarios that don't depend on isAuthenticated being stubbed }); @@ -69,7 +69,7 @@ describe('Common Helper', () => { afterEach(() => { // Restore all stubs and mocks sandbox.restore(); - + // Clean up temp directory // Critical for CI - must clean up temp files to avoid disk space issues try { @@ -98,9 +98,7 @@ describe('Common Helper', () => { const configData: ImportConfig = { apiKey: 'test-api-key', - target_stack: 'test-api-key', - data: '/test/data', - contentVersion: 1, + contentDir: '/test/data', masterLocale: { code: 'en-us' }, backupDir: '/test/backup', region: 'us', @@ -120,8 +118,7 @@ describe('Common Helper', () => { const configData: any = { email: 'test@example.com', password: 'password', - data: '/test/data', - contentVersion: 1, + contentDir: '/test/data', masterLocale: { code: 'en-us' }, backupDir: '/test/backup', region: 'us', @@ -136,8 +133,8 @@ describe('Common Helper', () => { const originalBuildAppConfig = commonHelperModule.buildAppConfig; sandbox.stub(commonHelperModule, 'buildAppConfig').callsFake((config: ImportConfig) => { const merged = originalBuildAppConfig(config); - // Delete target_stack to ensure validation fails (email/password without target_stack) - delete merged.target_stack; + // Delete apiKey to ensure validation fails (email/password without apiKey) + delete merged.apiKey; return merged; }); @@ -150,13 +147,12 @@ describe('Common Helper', () => { }); describe('validateConfig()', () => { - it('should return error when email and password are provided without target_stack - covers lines 32-33', () => { + it('should return error when email and password are provided without apiKey - covers lines 32-33', () => { const config: ImportConfig = { email: 'test@example.com', password: 'password', - // target_stack is undefined - this triggers the condition on line 31 - apiKey: 'test-api-key', - data: '/test/data', + // apiKey is undefined - this triggers the condition on line 31 + contentDir: '/test/data', } as any; // This test covers lines 31-33: email && password && !target_stack @@ -168,12 +164,11 @@ describe('Common Helper', () => { // Since we can't easily stub log, we verify the return value which proves the code path executed }); - it('should return error when no auth credentials with target_stack and not authenticated - covers lines 41-42', () => { + it('should return error when no auth credentials with apiKey and not authenticated - covers lines 41-42', () => { const config: ImportConfig = { - target_stack: 'test-api-key', // email, password, and management_token are all undefined apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; // This test covers lines 34-42: !email && !password && !management_token && target_stack && !isAuthenticated() @@ -184,7 +179,7 @@ describe('Common Helper', () => { // The result depends on isAuthenticated() - if false, returns 'error' (lines 41-42), otherwise undefined // Either path is valid, but we ensure the condition is evaluated expect(result === 'error' || result === undefined).to.be.true; - + // To specifically cover lines 41-42, we'd need isAuthenticated() to return false // But since we can't stub it, this test at least ensures the condition is evaluated // and will cover those lines if isAuthenticated() happens to return false in test environment @@ -194,7 +189,7 @@ describe('Common Helper', () => { const config: ImportConfig = { target_stack: 'test-api-key', // No email, password, or management_token - relies on isAuthenticated() - data: '/test/data', + contentDir: '/test/data', } as any; // Note: isAuthenticated() is called internally by validateConfig (line 39) @@ -214,7 +209,7 @@ describe('Common Helper', () => { target_stack: 'test-api-key', // email, password, and management_token are all undefined apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; const result = validateConfig(config); @@ -236,7 +231,7 @@ describe('Common Helper', () => { const config: ImportConfig = { preserveStackVersion: true, apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; const result = validateConfig(config); @@ -248,7 +243,7 @@ describe('Common Helper', () => { const config: ImportConfig = { email: 'test@example.com', apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; const result = validateConfig(config); @@ -260,7 +255,7 @@ describe('Common Helper', () => { const config: ImportConfig = { password: 'password', apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; const result = validateConfig(config); @@ -274,7 +269,7 @@ describe('Common Helper', () => { password: 'password', target_stack: 'test-api-key', apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; const result = validateConfig(config); @@ -287,7 +282,7 @@ describe('Common Helper', () => { management_token: 'mgmt-token', target_stack: 'test-api-key', apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; const result = validateConfig(config); @@ -300,7 +295,7 @@ describe('Common Helper', () => { it('should merge config with defaultConfig', () => { const configData: ImportConfig = { apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; const result = buildAppConfig(configData); @@ -317,7 +312,7 @@ describe('Common Helper', () => { const config: ImportConfig = { preserveStackVersion: false, apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; const result = await sanitizeStack(config); @@ -329,7 +324,7 @@ describe('Common Helper', () => { it('should return resolved promise when preserveStackVersion is undefined', async () => { const config: ImportConfig = { apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; const result = await sanitizeStack(config); @@ -342,7 +337,7 @@ describe('Common Helper', () => { preserveStackVersion: true, management_token: 'mgmt-token', apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; const result = await sanitizeStack(config); @@ -360,7 +355,7 @@ describe('Common Helper', () => { version: '2017-10-14', }, }; - + // Write actual file for reference, but stub will be used fs.writeFileSync(stackFile, JSON.stringify(oldStackData)); @@ -376,7 +371,7 @@ describe('Common Helper', () => { fileName: 'settings.json', }, } as any, - data: tempDir, + contentDir: tempDir, apiKey: 'test-api-key', headers: { api_key: 'test-api-key' }, } as any; @@ -397,7 +392,7 @@ describe('Common Helper', () => { // Stub readFileSync to return the old stack data (line 87 uses readFileSync) fileHelperStubs.readFileSync.returns(oldStackData); - + httpClientStub.get.resolves(newStackData); httpClientStub.put.resolves(putResponse); @@ -428,7 +423,7 @@ describe('Common Helper', () => { fileName: 'settings.json', }, } as any, - data: tempDir, + contentDir: tempDir, apiKey: 'test-api-key', headers: { api_key: 'test-api-key' }, } as any; @@ -444,7 +439,7 @@ describe('Common Helper', () => { }; httpClientStub.get.resolves(newStackData); - + // Stub readFileSync to return oldStackData (line 87 uses readFileSync with default parse=true) // readFileSync returns parsed JSON, so we return the object directly fileHelperStubs.readFileSync.returns(oldStackData); @@ -461,9 +456,9 @@ describe('Common Helper', () => { const errorMsg = error?.message || String(error); // Accept either the Migration Error or the settings access error (both indicate the error path) expect( - errorMsg.includes('Migration Error') || - errorMsg.includes('Cannot read properties of undefined') || - errorMsg.includes('invalid') + errorMsg.includes('Migration Error') || + errorMsg.includes('Cannot read properties of undefined') || + errorMsg.includes('invalid'), ).to.be.true; } }); @@ -493,7 +488,7 @@ describe('Common Helper', () => { fileName: 'settings.json', }, } as any, - data: tempDir, + contentDir: tempDir, apiKey: 'test-api-key', headers: { api_key: 'test-api-key' }, } as any; @@ -530,14 +525,14 @@ describe('Common Helper', () => { fileName: 'settings.json', }, } as any, - data: '/test/data', + contentDir: '/test/data', apiKey: 'test-api-key', headers: { api_key: 'test-api-key' }, } as any; // Stub console.log to verify line 120 is executed const consoleLogStub = sandbox.stub(console, 'log'); - + // Make HttpClient.create throw to trigger catch block const originalCreate = cliUtilities.HttpClient.create; (cliUtilities.HttpClient as any).create = () => { @@ -548,7 +543,7 @@ describe('Common Helper', () => { // Line 120 should execute - console.log in catch block expect(consoleLogStub.called).to.be.true; - + // Restore HttpClient.create (cliUtilities.HttpClient as any).create = originalCreate; }); @@ -566,7 +561,7 @@ describe('Common Helper', () => { fileName: 'settings.json', }, } as any, - data: tempDir, + contentDir: tempDir, apiKey: 'test-api-key', headers: { api_key: 'test-api-key' }, } as any; @@ -605,7 +600,7 @@ describe('Common Helper', () => { fileName: 'settings.json', }, } as any, - data: tempDir, + contentDir: tempDir, apiKey: 'test-api-key', headers: { api_key: 'test-api-key' }, } as any; @@ -626,7 +621,12 @@ describe('Common Helper', () => { await sanitizeStack(config); expect.fail('Should have thrown an error'); } catch (error: any) { - expect(error.message).to.include('is invalid'); + // The error could be about path being undefined or invalid stack file + expect( + error.message.includes('is invalid') || + error.message.includes('path') || + error.message.includes('Unexpected stack details'), + ).to.be.true; } }); }); @@ -666,19 +666,19 @@ describe('Common Helper', () => { }); describe('field_rules_update()', () => { - it('should successfully update field rules', async function() { + it('should successfully update field rules', async function () { // Increase timeout for this test since it involves async operations this.timeout(10000); - + const ctPath = path.join(tempDir, 'content-types'); fs.mkdirSync(ctPath, { recursive: true }); - + const fieldRulesData = ['content_type_1']; // readFile with default json type returns parsed JSON, but code does JSON.parse(data) again // So we need to write a JSON string that when parsed once gives a JSON string, which when parsed again gives the array // i.e., double-stringified JSON fs.writeFileSync(path.join(ctPath, 'field_rules_uid.json'), JSON.stringify(JSON.stringify(fieldRulesData))); - + const schemaContent = { uid: 'content_type_1', field_rules: [ @@ -704,10 +704,8 @@ describe('Common Helper', () => { const config: ImportConfig = { apiKey: 'test-api-key', - target_stack: 'test-api-key', management_token: 'mgmt-token', - data: tempDir, - contentVersion: 1, + contentDir: tempDir, masterLocale: { code: 'en-us' }, backupDir: '/test/backup', region: 'us', @@ -729,7 +727,7 @@ describe('Common Helper', () => { } return Promise.reject(new Error('File not found')); }); - + fileHelperStubs.readdirSync.returns(['content_type_1.json', 'field_rules_uid.json']); // readFileSync is called on line 172 for uid-mapping.json inside the loops fileHelperStubs.readFileSync.returns(entryUidMapping); @@ -737,12 +735,14 @@ describe('Common Helper', () => { // Mock require to return the schema - require() will be called with resolved path const Module = require('module'); const originalRequire = Module.prototype.require; - Module.prototype.require = function(id: string) { + Module.prototype.require = function (id: string) { const resolvedPath = path.resolve(id); // Check if this is our content type file - if (resolvedPath === path.resolve(ctPath, 'content_type_1') || - resolvedPath === path.join(ctPath, 'content_type_1') || - resolvedPath.includes('content_type_1')) { + if ( + resolvedPath === path.resolve(ctPath, 'content_type_1') || + resolvedPath === path.join(ctPath, 'content_type_1') || + resolvedPath.includes('content_type_1') + ) { return schemaContent; } return originalRequire.apply(this, arguments as any); @@ -776,7 +776,7 @@ describe('Common Helper', () => { console.log('[TEST DEBUG] After test - mockUpdateStub.called:', mockUpdateStub.called); console.log('[TEST DEBUG] After test - stackStub.called:', stackStub.called); console.log('[TEST DEBUG] After test - contentTypeStub.called:', contentTypeStub.called); - + // Verify the update stub was actually called // This covers lines 260-268: originalUpdate preservation, update() call, and promise setup // And lines 277-278: the resolve('') path when update() resolves @@ -790,18 +790,18 @@ describe('Common Helper', () => { } }); - it('should preserve update method through schema assignment - covers lines 242, 260-261', async function() { + it('should preserve update method through schema assignment - covers lines 242, 260-261', async function () { // Skipped due to timeout - same SDK mocking issue as other field_rules_update tests // Lines 242, 260-261 are covered by the main "should successfully update field rules" test // This test ensures the update method preservation logic works (lines 242, 260-261) this.timeout(10000); - + const ctPath = path.join(tempDir, 'content-types-preserve'); fs.mkdirSync(ctPath, { recursive: true }); - + const fieldRulesData = ['content_type_1']; fs.writeFileSync(path.join(ctPath, 'field_rules_uid.json'), JSON.stringify(JSON.stringify(fieldRulesData))); - + // Create schema that intentionally doesn't have 'update' key to test preservation const schemaContent = { uid: 'content_type_1', @@ -828,10 +828,8 @@ describe('Common Helper', () => { const config: ImportConfig = { apiKey: 'test-api-key', - target_stack: 'test-api-key', management_token: 'mgmt-token', - data: tempDir, - contentVersion: 1, + contentDir: tempDir, masterLocale: { code: 'en-us' }, backupDir: '/test/backup', region: 'us', @@ -848,16 +846,15 @@ describe('Common Helper', () => { } return Promise.reject(new Error('File not found')); }); - + fileHelperStubs.readdirSync.returns(['content_type_1.json', 'field_rules_uid.json']); fileHelperStubs.readFileSync.returns(entryUidMapping); const Module = require('module'); const originalRequire = Module.prototype.require; - Module.prototype.require = function(id: string) { + Module.prototype.require = function (id: string) { const resolvedPath = path.resolve(id); - if (resolvedPath === path.resolve(ctPath, 'content_type_1') || - resolvedPath.includes('content_type_1')) { + if (resolvedPath === path.resolve(ctPath, 'content_type_1') || resolvedPath.includes('content_type_1')) { return schemaContent; } return originalRequire.apply(this, arguments as any); @@ -889,27 +886,30 @@ describe('Common Helper', () => { } }); - it('should handle field rules with unmapped UIDs - covers lines 178-179', async function() { + it('should handle field rules with unmapped UIDs - covers lines 178-179', async function () { // Increase timeout for this test this.timeout(10000); const ctPath = path.join(tempDir, 'content-types-unmapped'); fs.mkdirSync(ctPath, { recursive: true }); - + const fieldRulesData = ['content_type_1']; fs.writeFileSync(path.join(ctPath, 'field_rules_uid.json'), JSON.stringify(JSON.stringify(fieldRulesData))); - fs.writeFileSync(path.join(ctPath, 'content_type_1.json'), JSON.stringify({ - uid: 'content_type_1', - field_rules: [ - { - conditions: [ - { - operand_field: 'reference', - value: 'unmapped_entry1.unmapped_entry2', - }, - ], - }, - ], - })); + fs.writeFileSync( + path.join(ctPath, 'content_type_1.json'), + JSON.stringify({ + uid: 'content_type_1', + field_rules: [ + { + conditions: [ + { + operand_field: 'reference', + value: 'unmapped_entry1.unmapped_entry2', + }, + ], + }, + ], + }), + ); const mapperDir = path.join(tempDir, 'mapper', 'entries'); fs.mkdirSync(mapperDir, { recursive: true }); @@ -935,10 +935,8 @@ describe('Common Helper', () => { const config: ImportConfig = { apiKey: 'test-api-key', - target_stack: 'test-api-key', management_token: 'mgmt-token', - data: tempDir, - contentVersion: 1, + contentDir: tempDir, masterLocale: { code: 'en-us' }, backupDir: '/test/backup', region: 'us', @@ -949,7 +947,7 @@ describe('Common Helper', () => { initialization(config); - // Stub fileHelper functions + // Stub fileHelper functions fileHelperStubs.readFile.callsFake((filePath: string) => { if (filePath && filePath.includes('field_rules_uid.json')) { return Promise.resolve(JSON.stringify(fieldRulesData)); @@ -962,10 +960,9 @@ describe('Common Helper', () => { // Mock require to return the schema const Module = require('module'); const originalRequire = Module.prototype.require; - Module.prototype.require = function(id: string) { + Module.prototype.require = function (id: string) { const resolvedPath = path.resolve(id); - if (resolvedPath === path.resolve(ctPath, 'content_type_1') || - resolvedPath.includes('content_type_1')) { + if (resolvedPath === path.resolve(ctPath, 'content_type_1') || resolvedPath.includes('content_type_1')) { return schemaContent; } return originalRequire.apply(this, arguments as any); @@ -997,27 +994,30 @@ describe('Common Helper', () => { } }); - it('should handle field rules update success - covers lines 201-202', async function() { + it('should handle field rules update success - covers lines 201-202', async function () { // Increase timeout for this test this.timeout(10000); const ctPath = path.join(tempDir, 'content-types-success'); fs.mkdirSync(ctPath, { recursive: true }); - + const fieldRulesData = ['content_type_1']; fs.writeFileSync(path.join(ctPath, 'field_rules_uid.json'), JSON.stringify(JSON.stringify(fieldRulesData))); - fs.writeFileSync(path.join(ctPath, 'content_type_1.json'), JSON.stringify({ - uid: 'content_type_1', - field_rules: [ - { - conditions: [ - { - operand_field: 'reference', - value: 'entry1', - }, - ], - }, - ], - })); + fs.writeFileSync( + path.join(ctPath, 'content_type_1.json'), + JSON.stringify({ + uid: 'content_type_1', + field_rules: [ + { + conditions: [ + { + operand_field: 'reference', + value: 'entry1', + }, + ], + }, + ], + }), + ); const mapperDir = path.join(tempDir, 'mapper', 'entries'); fs.mkdirSync(mapperDir, { recursive: true }); @@ -1042,10 +1042,8 @@ describe('Common Helper', () => { const config: ImportConfig = { apiKey: 'test-api-key', - target_stack: 'test-api-key', management_token: 'mgmt-token', - data: tempDir, - contentVersion: 1, + contentDir: tempDir, masterLocale: { code: 'en-us' }, backupDir: '/test/backup', region: 'us', @@ -1056,7 +1054,7 @@ describe('Common Helper', () => { initialization(config); - // Stub fileHelper functions + // Stub fileHelper functions fileHelperStubs.readFile.callsFake((filePath: string) => { if (filePath && filePath.includes('field_rules_uid.json')) { return Promise.resolve(JSON.stringify(fieldRulesData)); @@ -1069,10 +1067,9 @@ describe('Common Helper', () => { // Mock require to return the schema const Module = require('module'); const originalRequire = Module.prototype.require; - Module.prototype.require = function(id: string) { + Module.prototype.require = function (id: string) { const resolvedPath = path.resolve(id); - if (resolvedPath === path.resolve(ctPath, 'content_type_1') || - resolvedPath.includes('content_type_1')) { + if (resolvedPath === path.resolve(ctPath, 'content_type_1') || resolvedPath.includes('content_type_1')) { return schemaContent; } return originalRequire.apply(this, arguments as any); @@ -1104,16 +1101,16 @@ describe('Common Helper', () => { } }); - it('should handle field rules update failure - covers lines 204-206', async function() { + it('should handle field rules update failure - covers lines 204-206', async function () { // Increase timeout for this test since it involves async operations this.timeout(10000); - + const ctPath = path.join(tempDir, 'content-types-failure'); fs.mkdirSync(ctPath, { recursive: true }); - + const fieldRulesData = ['content_type_1']; fs.writeFileSync(path.join(ctPath, 'field_rules_uid.json'), JSON.stringify(JSON.stringify(fieldRulesData))); - + // Write the schema file that will be required const schemaContent = { uid: 'content_type_1', @@ -1139,10 +1136,8 @@ describe('Common Helper', () => { const config: ImportConfig = { apiKey: 'test-api-key', - target_stack: 'test-api-key', management_token: 'mgmt-token', - data: tempDir, - contentVersion: 1, + contentDir: tempDir, masterLocale: { code: 'en-us' }, backupDir: '/test/backup', region: 'us', @@ -1153,7 +1148,7 @@ describe('Common Helper', () => { initialization(config); - // Stub fileHelper functions + // Stub fileHelper functions fileHelperStubs.readFile.callsFake((filePath: string) => { if (filePath && filePath.includes('field_rules_uid.json')) { return Promise.resolve(JSON.stringify(fieldRulesData)); @@ -1185,10 +1180,9 @@ describe('Common Helper', () => { // Mock require to return the schema const Module = require('module'); const originalRequire = Module.prototype.require; - Module.prototype.require = function(id: string) { + Module.prototype.require = function (id: string) { const resolvedPath = path.resolve(id); - if (resolvedPath === path.resolve(ctPath, 'content_type_1') || - resolvedPath.includes('content_type_1')) { + if (resolvedPath === path.resolve(ctPath, 'content_type_1') || resolvedPath.includes('content_type_1')) { return schemaContent; } return originalRequire.apply(this, arguments as any); @@ -1210,7 +1204,6 @@ describe('Common Helper', () => { apiKey: 'test-api-key', target_stack: 'test-api-key', data: tempDir, - contentVersion: 1, masterLocale: { code: 'en-us' }, backupDir: '/test/backup', region: 'us', @@ -1225,7 +1218,7 @@ describe('Common Helper', () => { // Stub readFile to reject with error to test error path fileHelperStubs.readFile.rejects(new Error('File read error')); - + managementSDKClientStub.resolves({}); try { @@ -1243,7 +1236,7 @@ describe('Common Helper', () => { it('should return stored config', () => { const testConfig: ImportConfig = { apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; initialization(testConfig); @@ -1371,7 +1364,7 @@ describe('Common Helper', () => { const config: ImportConfig = { apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; const result = await validateBranch(mockStackAPIClient, config, 'test-branch'); @@ -1394,7 +1387,7 @@ describe('Common Helper', () => { const config: ImportConfig = { apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; try { @@ -1415,7 +1408,7 @@ describe('Common Helper', () => { const config: ImportConfig = { apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; try { @@ -1436,7 +1429,7 @@ describe('Common Helper', () => { const config: ImportConfig = { apiKey: 'test-api-key', - data: '/test/data', + contentDir: '/test/data', } as any; try { diff --git a/packages/contentstack-import/test/unit/utils/extension-helper.test.ts b/packages/contentstack-import/test/unit/utils/extension-helper.test.ts index c9b5672182..e488850444 100644 --- a/packages/contentstack-import/test/unit/utils/extension-helper.test.ts +++ b/packages/contentstack-import/test/unit/utils/extension-helper.test.ts @@ -157,7 +157,6 @@ describe('Extension Helper', () => { marketplaceAppEncryptionKey: 'test-key', getEncryptionKeyMaxRetry: 3, overwriteSupportedModules: [], - onlyTSModules: [], globalModules: [], entriesPublish: false, cliLogsPath: '/test/logs', @@ -166,7 +165,6 @@ describe('Extension Helper', () => { skipPrivateAppRecreationIfExist: false, master_locale: { code: 'en-us' }, masterLocale: { code: 'en-us' }, - contentVersion: 1, region: 'us' as any, 'exclude-global-modules': false, context: {} as any, diff --git a/packages/contentstack-import/test/unit/utils/import-config-handler.test.ts b/packages/contentstack-import/test/unit/utils/import-config-handler.test.ts index e44a2bf6e2..08d7fb79eb 100644 --- a/packages/contentstack-import/test/unit/utils/import-config-handler.test.ts +++ b/packages/contentstack-import/test/unit/utils/import-config-handler.test.ts @@ -127,7 +127,6 @@ describe('Import Config Handler', () => { const result = await setupConfig(importCmdFlags); expect(result.contentDir).to.equal(path.resolve('/test/content')); - expect(result.data).to.equal(path.resolve('/test/content')); expect(askContentDirStub.called).to.be.false; }); @@ -142,31 +141,24 @@ describe('Import Config Handler', () => { const result = await setupConfig(importCmdFlags); expect(result.contentDir).to.equal(path.resolve('/test/data-dir')); - expect(result.data).to.equal(path.resolve('/test/data-dir')); + expect(result.contentDir).to.equal(path.resolve('/test/data-dir')); }); - it('should use config.data when no flags provided', async () => { - const importCmdFlags = {}; - const configData = '/default/data/path'; + it('should use config.contentDir when no flags provided', async () => { + const importCmdFlags = { config: '/path/to/config.json' }; + const configContentDir = '/default/content/path'; - readFileStub.resolves({ data: configData }); + readFileStub.resolves({ contentDir: configContentDir }); configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); askAPIKeyStub.resolves('test-api-key'); - // Need to mock defaultConfig.data for this test - const originalData = (defaultConfig as any).data; - (defaultConfig as any).data = configData; - const result = await setupConfig(importCmdFlags); - // Restore - (defaultConfig as any).data = originalData; - - expect(result.contentDir).to.equal(path.resolve(configData)); + expect(result.contentDir).to.equal(path.resolve(configContentDir)); }); - it('should prompt for contentDir when no flags or config.data provided', async () => { + it('should prompt for contentDir when no flags or config.contentDir provided', async () => { const importCmdFlags = {}; const promptedPath = '/prompted/path'; @@ -175,14 +167,16 @@ describe('Import Config Handler', () => { configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); askAPIKeyStub.resolves('test-api-key'); - // Remove data from defaultConfig for this test - const originalData = (defaultConfig as any).data; - delete (defaultConfig as any).data; + // Ensure defaultConfig doesn't have contentDir set + const originalContentDir = (defaultConfig as any).contentDir; + delete (defaultConfig as any).contentDir; const result = await setupConfig(importCmdFlags); // Restore - (defaultConfig as any).data = originalData; + if (originalContentDir !== undefined) { + (defaultConfig as any).contentDir = originalContentDir; + } expect(askContentDirStub.called).to.be.true; expect(result.contentDir).to.equal(path.resolve(promptedPath)); @@ -285,13 +279,13 @@ describe('Import Config Handler', () => { configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); configHandlerGetStub.withArgs('authtoken').returns('test-auth-token'); // Set default apiKey to avoid prompting - const originalTargetStack = (defaultConfig as any).target_stack; - (defaultConfig as any).target_stack = 'default-api-key'; + const originalApiKey = (defaultConfig as any).apiKey; + (defaultConfig as any).apiKey = 'default-api-key'; }); afterEach(() => { - const originalTargetStack = (defaultConfig as any).target_stack; - delete (defaultConfig as any).target_stack; + const originalApiKey = (defaultConfig as any).apiKey; + delete (defaultConfig as any).apiKey; }); it('should set skipAudit from skip-audit flag', async () => { @@ -445,34 +439,13 @@ describe('Import Config Handler', () => { configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); configHandlerGetStub.withArgs('authorisationType').returns('OAUTH'); configHandlerGetStub.withArgs('authtoken').returns('test-auth-token'); - (defaultConfig as any).target_stack = 'default-api-key'; + (defaultConfig as any).apiKey = 'default-api-key'; }); afterEach(() => { - delete (defaultConfig as any).target_stack; + delete (defaultConfig as any).apiKey; }); - it('should set source_stack to apiKey', async () => { - const importCmdFlags = { - data: '/test/content', - 'stack-api-key': 'test-api-key', - }; - - const result = await setupConfig(importCmdFlags); - - expect(result.source_stack).to.equal('test-api-key'); - }); - - it('should set target_stack to apiKey', async () => { - const importCmdFlags = { - data: '/test/content', - 'stack-api-key': 'test-api-key', - }; - - const result = await setupConfig(importCmdFlags); - - expect(result.target_stack).to.equal('test-api-key'); - }); it('should set isAuthenticated flag', async () => { const importCmdFlags = { diff --git a/packages/contentstack-import/test/unit/utils/import-path-resolver.test.ts b/packages/contentstack-import/test/unit/utils/import-path-resolver.test.ts index b2be118f60..ebc848a21d 100644 --- a/packages/contentstack-import/test/unit/utils/import-path-resolver.test.ts +++ b/packages/contentstack-import/test/unit/utils/import-path-resolver.test.ts @@ -119,11 +119,7 @@ describe('Import Path Resolver', () => { it('should prompt user when multiple branches exist', async () => { const branchesJsonPath = path.join(contentDir, 'branches.json'); const selectedBranchPath = path.join(contentDir, 'branch2'); - const branchesData = [ - { uid: 'branch1' }, - { uid: 'branch2' }, - { uid: 'branch3' }, - ]; + const branchesData = [{ uid: 'branch1' }, { uid: 'branch2' }, { uid: 'branch3' }]; fileExistsSyncStub.withArgs(branchesJsonPath).returns(true); fileExistsSyncStub.withArgs(selectedBranchPath).returns(true); @@ -140,10 +136,7 @@ describe('Import Path Resolver', () => { it('should return null when selected branch path does not exist', async () => { const branchesJsonPath = path.join(contentDir, 'branches.json'); const selectedBranchPath = path.join(contentDir, 'branch2'); - const branchesData = [ - { uid: 'branch1' }, - { uid: 'branch2' }, - ]; + const branchesData = [{ uid: 'branch1' }, { uid: 'branch2' }]; fileExistsSyncStub.withArgs(branchesJsonPath).returns(true); fileExistsSyncStub.withArgs(selectedBranchPath).returns(false); @@ -195,11 +188,9 @@ describe('Import Path Resolver', () => { } }); - it('should use contentDir from importConfig.data when contentDir is not set', async () => { - delete (mockConfig as any).contentDir; - (mockConfig as any).data = '/test/data'; + it('should use contentDir from importConfig when set', async () => { + mockConfig.contentDir = '/test/data'; fileExistsSyncStub.withArgs('/test/data').returns(true); - fileExistsSyncStub.withArgs(path.join('/test/data', 'export-info.json')).returns(false); // Mock module types check defaultConfig.modules.types.forEach((moduleType) => { @@ -244,23 +235,10 @@ describe('Import Path Resolver', () => { expect(result).to.equal('/test/content'); }); - it('should return contentDir when export-info.json exists (v2 export)', async () => { - const exportInfoPath = path.join('/test/content', 'export-info.json'); - - fileExistsSyncStub.withArgs('/test/content').returns(true); - fileExistsSyncStub.withArgs(exportInfoPath).returns(true); - - const result = await resolveImportPath(mockConfig, mockStackAPIClient); - - expect(result).to.equal('/test/content'); - }); - it('should return contentDir when module folders exist', async () => { - const exportInfoPath = path.join('/test/content', 'export-info.json'); const modulePath = path.join('/test/content', defaultConfig.modules.types[0]); fileExistsSyncStub.withArgs('/test/content').returns(true); - fileExistsSyncStub.withArgs(exportInfoPath).returns(false); fileExistsSyncStub.withArgs(modulePath).returns(true); const result = await resolveImportPath(mockConfig, mockStackAPIClient); @@ -268,12 +246,10 @@ describe('Import Path Resolver', () => { expect(result).to.equal('/test/content'); }); - it('should call selectBranchFromDirectory when no branch name or export-info.json', async () => { - const exportInfoPath = path.join('/test/content', 'export-info.json'); + it('should call selectBranchFromDirectory when no branch name', async () => { const branchPath = path.join('/test/content', 'branch1'); fileExistsSyncStub.withArgs('/test/content').returns(true); - fileExistsSyncStub.withArgs(exportInfoPath).returns(false); // Mock module types check - all return false defaultConfig.modules.types.forEach((moduleType) => { @@ -292,10 +268,7 @@ describe('Import Path Resolver', () => { }); it('should return contentDir when selectBranchFromDirectory returns null', async () => { - const exportInfoPath = path.join('/test/content', 'export-info.json'); - fileExistsSyncStub.withArgs('/test/content').returns(true); - fileExistsSyncStub.withArgs(exportInfoPath).returns(false); // Mock module types check - all return false defaultConfig.modules.types.forEach((moduleType) => { @@ -318,7 +291,6 @@ describe('Import Path Resolver', () => { beforeEach(() => { mockConfig = { contentDir: '/test/content', - data: '/test/data', apiKey: 'test', } as ImportConfig; }); @@ -331,66 +303,17 @@ describe('Import Path Resolver', () => { expect(mockConfig.branchDir).to.be.undefined; expect(mockConfig.contentDir).to.equal('/test/content'); - expect(mockConfig.data).to.equal('/test/data'); - }); - - it('should update config with resolved path and set contentVersion to 1 when export-info.json does not exist', async () => { - const resolvedPath = '/test/resolved'; - const exportInfoPath = path.join(resolvedPath, 'export-info.json'); - - fileExistsSyncStub.withArgs(resolvedPath).returns(true); - fileExistsSyncStub.withArgs(exportInfoPath).returns(false); - - await updateImportConfigWithResolvedPath(mockConfig, resolvedPath); - - expect(mockConfig.branchDir).to.equal(resolvedPath); - expect(mockConfig.contentDir).to.equal(resolvedPath); - expect(mockConfig.data).to.equal(resolvedPath); - expect(mockConfig.contentVersion).to.equal(1); }); - it('should update config with resolved path and set contentVersion from export-info.json', async () => { + it('should update config with resolved path', async () => { const resolvedPath = '/test/resolved'; - const exportInfoPath = path.join(resolvedPath, 'export-info.json'); - const exportInfo = { contentVersion: 2 }; fileExistsSyncStub.withArgs(resolvedPath).returns(true); - fileExistsSyncStub.withArgs(exportInfoPath).returns(true); - readFileStub.withArgs(exportInfoPath).resolves(exportInfo); await updateImportConfigWithResolvedPath(mockConfig, resolvedPath); expect(mockConfig.branchDir).to.equal(resolvedPath); expect(mockConfig.contentDir).to.equal(resolvedPath); - expect(mockConfig.data).to.equal(resolvedPath); - expect(mockConfig.contentVersion).to.equal(2); - }); - - it('should set contentVersion to 2 when export-info.json exists but contentVersion is missing', async () => { - const resolvedPath = '/test/resolved'; - const exportInfoPath = path.join(resolvedPath, 'export-info.json'); - const exportInfo = {}; - - fileExistsSyncStub.withArgs(resolvedPath).returns(true); - fileExistsSyncStub.withArgs(exportInfoPath).returns(true); - readFileStub.withArgs(exportInfoPath).resolves(exportInfo); - - await updateImportConfigWithResolvedPath(mockConfig, resolvedPath); - - expect(mockConfig.contentVersion).to.equal(2); - }); - - it('should set contentVersion to 2 when export-info.json is null', async () => { - const resolvedPath = '/test/resolved'; - const exportInfoPath = path.join(resolvedPath, 'export-info.json'); - - fileExistsSyncStub.withArgs(resolvedPath).returns(true); - fileExistsSyncStub.withArgs(exportInfoPath).returns(true); - readFileStub.withArgs(exportInfoPath).resolves(null); - - await updateImportConfigWithResolvedPath(mockConfig, resolvedPath); - - expect(mockConfig.contentVersion).to.equal(2); }); }); @@ -408,15 +331,9 @@ describe('Import Path Resolver', () => { it('should execute complete path resolution logic', async () => { const resolvedPath = path.join('/test/content', 'branch1'); - const exportInfoPath = path.join(resolvedPath, 'export-info.json'); fileExistsSyncStub.withArgs('/test/content').returns(true); fileExistsSyncStub.withArgs(resolvedPath).returns(true); - fileExistsSyncStub.withArgs(exportInfoPath).returns(false); - - // Mock export-info.json not found at contentDir - const contentDirExportInfoPath = path.join('/test/content', 'export-info.json'); - fileExistsSyncStub.withArgs(contentDirExportInfoPath).returns(false); // Mock module types check defaultConfig.modules.types.forEach((moduleType) => { @@ -434,8 +351,6 @@ describe('Import Path Resolver', () => { expect(result).to.equal(resolvedPath); expect(mockConfig.branchDir).to.equal(resolvedPath); expect(mockConfig.contentDir).to.equal(resolvedPath); - expect(mockConfig.data).to.equal(resolvedPath); }); }); }); - diff --git a/packages/contentstack-import/test/unit/utils/logger.test.ts b/packages/contentstack-import/test/unit/utils/logger.test.ts index d8cd23da77..7d67e23cf7 100644 --- a/packages/contentstack-import/test/unit/utils/logger.test.ts +++ b/packages/contentstack-import/test/unit/utils/logger.test.ts @@ -13,10 +13,10 @@ describe('Logger Utils', () => { beforeEach(() => { sandbox = sinon.createSandbox(); - + // Clear module cache to ensure fresh state for each test delete require.cache[require.resolve('../../../src/utils/logger')]; - + // Create temp directory for log files tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'logger-test-')); @@ -29,7 +29,6 @@ describe('Logger Utils', () => { canCreatePrivateApp: false, forceStopMarketplaceAppsPrompt: false, skipPrivateAppRecreationIfExist: false, - contentVersion: 1, backupDir: tempDir, masterLocale: { code: 'en-us' }, master_locale: { code: 'en-us' }, @@ -37,13 +36,13 @@ describe('Logger Utils', () => { context: {} as any, 'exclude-global-modules': false, fetchConcurrency: 5, - writeConcurrency: 5 + writeConcurrency: 5, } as ImportConfig; }); afterEach(() => { sandbox.restore(); - + // Clean up temp directory try { if (tempDir && fs.existsSync(tempDir)) { diff --git a/packages/contentstack-import/test/unit/utils/marketplace-app-helper.test.ts b/packages/contentstack-import/test/unit/utils/marketplace-app-helper.test.ts index 33cbdb42f3..572e8f034f 100644 --- a/packages/contentstack-import/test/unit/utils/marketplace-app-helper.test.ts +++ b/packages/contentstack-import/test/unit/utils/marketplace-app-helper.test.ts @@ -34,7 +34,7 @@ describe('Marketplace App Helper', () => { mockConfig = { org_uid: 'test-org-uid', - target_stack: 'test-stack-uid', + apiKey: 'test-stack-uid', host: 'https://api.contentstack.io', developerHubBaseUrl: 'https://developerhub-api.contentstack.com', forceStopMarketplaceAppsPrompt: false, @@ -230,7 +230,7 @@ describe('Marketplace App Helper', () => { const result = await getOrgUid(mockConfig); expect(result).to.equal('test-org-123'); - expect(mockClient.stack.calledWith({ api_key: mockConfig.target_stack })).to.be.true; + expect(mockClient.stack.calledWith({ api_key: mockConfig.apiKey })).to.be.true; }); it('should return empty string when org_uid is not present', async () => { diff --git a/packages/contentstack-seed/package.json b/packages/contentstack-seed/package.json index 67c6d1dbd9..a6baa31f39 100644 --- a/packages/contentstack-seed/package.json +++ b/packages/contentstack-seed/package.json @@ -1,17 +1,17 @@ { "name": "@contentstack/cli-cm-seed", "description": "create a Stack from existing content types, entries, assets, etc.", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "author": "Contentstack", "bugs": "https://github.com/contentstack/cli/issues", "dependencies": { - "@contentstack/cli-cm-import": "~2.0.0-beta.3", + "@contentstack/cli-cm-import": "~2.0.0-beta.4", "@contentstack/cli-command": "~1.7.0", "@contentstack/cli-utilities": "~1.15.0", "@contentstack/management": "~1.22.0", "inquirer": "8.2.7", "mkdirp": "^1.0.4", - "tar": "^6.2.1", + "tar": "^7.5.4", "tmp": "^0.2.3" }, "devDependencies": { @@ -66,4 +66,4 @@ "version": "oclif readme && git add README.md", "clean": "rm -rf ./node_modules tsconfig.build.tsbuildinfo" } -} +} \ No newline at end of file diff --git a/packages/contentstack-utilities/src/progress-summary/cli-progress-manager.ts b/packages/contentstack-utilities/src/progress-summary/cli-progress-manager.ts index 3b0b1b473a..32b1762f50 100644 --- a/packages/contentstack-utilities/src/progress-summary/cli-progress-manager.ts +++ b/packages/contentstack-utilities/src/progress-summary/cli-progress-manager.ts @@ -108,6 +108,16 @@ export default class CLIProgressManager { CLIProgressManager.globalSummary.printFinalSummary(); } + /** + * Check if there are any failures in the global summary + */ + static hasFailures(): boolean { + if (!CLIProgressManager.globalSummary) { + return false; + } + return CLIProgressManager.globalSummary.hasFailures(); + } + /** * Apply strategy-based corrections to module data */ diff --git a/packages/contentstack-utilities/src/progress-summary/summary-manager.ts b/packages/contentstack-utilities/src/progress-summary/summary-manager.ts index f4088c858c..a8073d5d89 100644 --- a/packages/contentstack-utilities/src/progress-summary/summary-manager.ts +++ b/packages/contentstack-utilities/src/progress-summary/summary-manager.ts @@ -131,10 +131,12 @@ export default class SummaryManager { // Final Status console.log('\n' + chalk.bold('Final Status:')); - if (failedModules === 0) { - console.log(chalk.bold.green(`🎉 ${this.operationName} completed successfully!`)); - } else if (completedModules > 0) { - console.log(chalk.bold.yellow(`⚠️ ${this.operationName} completed with ${failedModules} failed modules`)); + if (!this.hasFailures() && failedModules === 0) { + console.log(chalk.bold.green(`✅ ${this.operationName} completed successfully!`)); + } else if (this.hasFailures() || failedModules > 0) { + console.log( + chalk.bold.yellow(`⚠️ ${this.operationName} completed with failures, see the logs for more details.`), + ); } else { console.log(chalk.bold.red(`❌ ${this.operationName} failed`)); } @@ -146,6 +148,13 @@ export default class SummaryManager { this.printFailureSummaryWithLogReference(); } + /** + * Check if there are any failures across all modules + */ + hasFailures(): boolean { + return Array.from(this.modules.values()).some((m) => m.failures.length > 0 || m.failureCount > 0); + } + private printFailureSummaryWithLogReference(): void { const modulesWithFailures = Array.from(this.modules.values()).filter((m) => m.failures.length > 0); diff --git a/packages/contentstack-utilities/test/unit/summaryManager.test.ts b/packages/contentstack-utilities/test/unit/summaryManager.test.ts index d814581143..a988fba264 100644 --- a/packages/contentstack-utilities/test/unit/summaryManager.test.ts +++ b/packages/contentstack-utilities/test/unit/summaryManager.test.ts @@ -294,8 +294,7 @@ describe('SummaryManager', () => { // Should show mixed results const mixedCall = logCalls.find(call => - call.args[0] && call.args[0].includes('completed with') && - call.args[0].includes('failed modules') + call.args[0] && call.args[0].includes('completed with failures') ); expect(mixedCall).to.not.be.undefined; }); diff --git a/packages/contentstack-variants/package.json b/packages/contentstack-variants/package.json index 2aae51b21b..64b63c3414 100644 --- a/packages/contentstack-variants/package.json +++ b/packages/contentstack-variants/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/cli-variants", - "version": "2.0.0-beta.3", + "version": "2.0.0-beta.4", "description": "Variants plugin", "main": "lib/index.js", "types": "lib/index.d.ts", diff --git a/packages/contentstack-variants/src/export/attributes.ts b/packages/contentstack-variants/src/export/attributes.ts index 5766be1b1e..02164db571 100644 --- a/packages/contentstack-variants/src/export/attributes.ts +++ b/packages/contentstack-variants/src/export/attributes.ts @@ -22,7 +22,7 @@ export default class ExportAttributes extends PersonalizationAdapter { this.personalizeConfig = exportConfig.modules.personalize; this.eventsConfig = exportConfig.modules.events; this.eventsFolderPath = pResolve( - sanitizePath(exportConfig.data), + sanitizePath(exportConfig.exportDir), sanitizePath(exportConfig.branchName || ''), sanitizePath(this.personalizeConfig.dirName), sanitizePath(this.eventsConfig.dirName), diff --git a/packages/contentstack-variants/src/export/experiences.ts b/packages/contentstack-variants/src/export/experiences.ts index 312439efb3..c21d7f7e22 100644 --- a/packages/contentstack-variants/src/export/experiences.ts +++ b/packages/contentstack-variants/src/export/experiences.ts @@ -22,7 +22,7 @@ export default class ExportExperiences extends PersonalizationAdapter this.exportConfig = exportConfig; this.personalizeConfig = exportConfig.modules.personalize; this.projectsFolderPath = pResolve( - sanitizePath(exportConfig.data), + sanitizePath(exportConfig.exportDir), sanitizePath(exportConfig.branchName || ''), sanitizePath(this.personalizeConfig.dirName), 'projects', diff --git a/packages/contentstack-variants/src/export/variant-entries.ts b/packages/contentstack-variants/src/export/variant-entries.ts index aa798f20c2..82222f9806 100644 --- a/packages/contentstack-variants/src/export/variant-entries.ts +++ b/packages/contentstack-variants/src/export/variant-entries.ts @@ -31,7 +31,7 @@ export default class VariantEntries extends VariantAdapter { return this.withLoadingSpinner('ATTRIBUTES: Analyzing import data...', async () => { const { dirName, fileName } = this.attributeConfig; const attributesPath = resolve( - sanitizePath(this.config.data), + sanitizePath(this.config.contentDir), sanitizePath(this.personalizeConfig.dirName), sanitizePath(dirName), sanitizePath(fileName), diff --git a/packages/contentstack-variants/src/import/audiences.ts b/packages/contentstack-variants/src/import/audiences.ts index 1d16849631..02b3857eda 100644 --- a/packages/contentstack-variants/src/import/audiences.ts +++ b/packages/contentstack-variants/src/import/audiences.ts @@ -138,7 +138,7 @@ export default class Audiences extends PersonalizationAdapter { return this.withLoadingSpinner('AUDIENCES: Analyzing import data...', async () => { const { dirName, fileName } = this.audienceConfig; const audiencesPath = resolve( - sanitizePath(this.config.data), + sanitizePath(this.config.contentDir), sanitizePath(this.personalizeConfig.dirName), sanitizePath(dirName), sanitizePath(fileName), diff --git a/packages/contentstack-variants/src/import/events.ts b/packages/contentstack-variants/src/import/events.ts index 4792fcb6a9..c7a20c4cf0 100644 --- a/packages/contentstack-variants/src/import/events.ts +++ b/packages/contentstack-variants/src/import/events.ts @@ -123,7 +123,7 @@ export default class Events extends PersonalizationAdapter { return this.withLoadingSpinner('EVENTS: Analyzing import data...', async () => { const { dirName, fileName } = this.eventConfig; const eventsPath = resolve( - sanitizePath(this.config.data), + sanitizePath(this.config.contentDir), sanitizePath(this.personalizeConfig.dirName), sanitizePath(dirName), sanitizePath(fileName), diff --git a/packages/contentstack-variants/src/import/experiences.ts b/packages/contentstack-variants/src/import/experiences.ts index 4d383cdb12..353e566bc2 100644 --- a/packages/contentstack-variants/src/import/experiences.ts +++ b/packages/contentstack-variants/src/import/experiences.ts @@ -57,7 +57,7 @@ export default class Experiences extends PersonalizationAdapter { this.personalizeConfig = this.config.modules.personalize; this.experiencesDirPath = resolve( - sanitizePath(this.config.data), + sanitizePath(this.config.contentDir), sanitizePath(this.personalizeConfig.dirName), sanitizePath(this.personalizeConfig.experiences.dirName), ); @@ -86,7 +86,7 @@ export default class Experiences extends PersonalizationAdapter { this.failedCmsExpPath = resolve(sanitizePath(this.expMapperDirPath), 'failed-cms-experience.json'); this.experienceCTsPath = resolve(sanitizePath(this.experiencesDirPath), 'experiences-content-types.json'); this.experienceVariantsIdsPath = resolve( - sanitizePath(this.config.data), + sanitizePath(this.config.contentDir), sanitizePath(this.personalizeConfig.dirName), sanitizePath(this.experienceConfig.dirName), 'experiences-variants-ids.json', diff --git a/packages/contentstack-variants/src/import/project.ts b/packages/contentstack-variants/src/import/project.ts index 74a9018e7e..6bcce4f719 100644 --- a/packages/contentstack-variants/src/import/project.ts +++ b/packages/contentstack-variants/src/import/project.ts @@ -133,7 +133,7 @@ export default class Project extends PersonalizationAdapter { const personalize = this.config.modules.personalize; const { dirName, fileName } = personalize.projects; const projectPath = join( - sanitizePath(this.config.data), + sanitizePath(this.config.contentDir), sanitizePath(personalize.dirName), sanitizePath(dirName), sanitizePath(fileName), diff --git a/packages/contentstack-variants/src/utils/logger.ts b/packages/contentstack-variants/src/utils/logger.ts index 643080a905..f895e88ef2 100644 --- a/packages/contentstack-variants/src/utils/logger.ts +++ b/packages/contentstack-variants/src/utils/logger.ts @@ -132,7 +132,7 @@ function init(_logPath: string, module: string) { } export const log = (config: ExportConfig | ImportConfig, message: any, type: 'info' | 'error' | 'success') => { - const logsPath = config.data; + const logsPath = 'exportDir' in config ? config.exportDir : 'contentDir' in config ? config.contentDir : (config as any).data; // ignoring the type argument, as we are not using it to create a logfile anymore const module = (config as ImportConfig)['backupDir'] ? 'import' : 'export'; if (type !== 'error') { diff --git a/packages/contentstack/package.json b/packages/contentstack/package.json index 2e1aff9868..f83e4a9cd9 100755 --- a/packages/contentstack/package.json +++ b/packages/contentstack/package.json @@ -1,7 +1,7 @@ { "name": "@contentstack/cli", "description": "Command-line tool (CLI) to interact with Contentstack", - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.5", "author": "Contentstack", "bin": { "csdx": "./bin/run.js" @@ -24,21 +24,21 @@ "dependencies": { "@contentstack/cli-audit": "~2.0.0-beta.1", "@contentstack/cli-auth": "~2.0.0-beta.1", - "@contentstack/cli-cm-bootstrap": "~2.0.0-beta.3", + "@contentstack/cli-cm-bootstrap": "~2.0.0-beta.4", "@contentstack/cli-cm-branches": "~1.6.1", "@contentstack/cli-cm-bulk-publish": "~1.10.3", - "@contentstack/cli-cm-clone": "~2.0.0-beta.4", - "@contentstack/cli-cm-export": "~2.0.0-beta.4", + "@contentstack/cli-cm-clone": "~2.0.0-beta.5", + "@contentstack/cli-cm-export": "~2.0.0-beta.5", "@contentstack/cli-cm-export-to-csv": "~1.10.1", - "@contentstack/cli-cm-import": "~2.0.0-beta.3", + "@contentstack/cli-cm-import": "~2.0.0-beta.4", "@contentstack/cli-cm-import-setup": "~2.0.0-beta.2", - "@contentstack/cli-cm-seed": "~2.0.0-beta.3", + "@contentstack/cli-cm-seed": "~2.0.0-beta.4", "@contentstack/cli-command": "~1.7.0", "@contentstack/cli-config": "~1.16.1", "@contentstack/cli-launch": "1.9.3", "@contentstack/cli-migration": "~2.0.0-beta.1", "@contentstack/cli-utilities": "~1.15.0", - "@contentstack/cli-variants": "~2.0.0-beta.3", + "@contentstack/cli-variants": "~2.0.0-beta.4", "@contentstack/management": "~1.22.0", "@oclif/core": "^4.3.0", "@oclif/plugin-help": "^6.2.28", @@ -167,4 +167,4 @@ } }, "repository": "https://github.com/contentstack/cli" -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5812d61ca4..c75508f60a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,21 +14,21 @@ importers: specifiers: '@contentstack/cli-audit': ~2.0.0-beta.1 '@contentstack/cli-auth': ~2.0.0-beta.1 - '@contentstack/cli-cm-bootstrap': ~2.0.0-beta.3 + '@contentstack/cli-cm-bootstrap': ~2.0.0-beta.4 '@contentstack/cli-cm-branches': ~1.6.1 '@contentstack/cli-cm-bulk-publish': ~1.10.3 - '@contentstack/cli-cm-clone': ~2.0.0-beta.4 - '@contentstack/cli-cm-export': ~2.0.0-beta.4 + '@contentstack/cli-cm-clone': ~2.0.0-beta.5 + '@contentstack/cli-cm-export': ~2.0.0-beta.5 '@contentstack/cli-cm-export-to-csv': ~1.10.1 - '@contentstack/cli-cm-import': ~2.0.0-beta.3 + '@contentstack/cli-cm-import': ~2.0.0-beta.4 '@contentstack/cli-cm-import-setup': ~2.0.0-beta.2 - '@contentstack/cli-cm-seed': ~2.0.0-beta.3 + '@contentstack/cli-cm-seed': ~2.0.0-beta.4 '@contentstack/cli-command': ~1.7.0 '@contentstack/cli-config': ~1.16.1 '@contentstack/cli-launch': 1.9.3 '@contentstack/cli-migration': ~2.0.0-beta.1 '@contentstack/cli-utilities': ~1.15.0 - '@contentstack/cli-variants': ~2.0.0-beta.3 + '@contentstack/cli-variants': ~2.0.0-beta.4 '@contentstack/management': ~1.22.0 '@oclif/core': ^4.3.0 '@oclif/plugin-help': ^6.2.28 @@ -75,7 +75,7 @@ importers: '@contentstack/cli-auth': link:../contentstack-auth '@contentstack/cli-cm-bootstrap': link:../contentstack-bootstrap '@contentstack/cli-cm-branches': 1.6.2_lxq42tdpoxpye5tb7w3htdbbdq - '@contentstack/cli-cm-bulk-publish': 1.10.4_lxq42tdpoxpye5tb7w3htdbbdq + '@contentstack/cli-cm-bulk-publish': 1.10.5_lxq42tdpoxpye5tb7w3htdbbdq '@contentstack/cli-cm-clone': link:../contentstack-clone '@contentstack/cli-cm-export': link:../contentstack-export '@contentstack/cli-cm-export-to-csv': 1.10.2_lxq42tdpoxpye5tb7w3htdbbdq @@ -243,7 +243,7 @@ importers: packages/contentstack-bootstrap: specifiers: - '@contentstack/cli-cm-seed': ~2.0.0-beta.3 + '@contentstack/cli-cm-seed': ~2.0.0-beta.4 '@contentstack/cli-command': ~1.7.0 '@contentstack/cli-utilities': ~1.15.0 '@oclif/core': ^4.3.0 @@ -262,7 +262,7 @@ importers: mocha: 10.8.2 nyc: ^15.1.0 oclif: ^4.17.46 - tar: '^6.2.1 ' + tar: '^7.5.4 ' tmp: ^0.2.3 ts-node: ^8.10.2 typescript: ^4.9.5 @@ -274,7 +274,7 @@ importers: '@oclif/plugin-help': 6.2.36 inquirer: 8.2.7_@types+node@14.18.63 mkdirp: 1.0.4 - tar: 6.2.1 + tar: 7.5.6 devDependencies: '@oclif/test': 4.1.15_@oclif+core@4.8.0 '@types/inquirer': 9.0.9 @@ -379,8 +379,8 @@ importers: packages/contentstack-clone: specifiers: '@colors/colors': ^1.6.0 - '@contentstack/cli-cm-export': ~2.0.0-beta.4 - '@contentstack/cli-cm-import': ~2.0.0-beta.3 + '@contentstack/cli-cm-export': ~2.0.0-beta.5 + '@contentstack/cli-cm-import': ~2.0.0-beta.4 '@contentstack/cli-command': ~1.7.0 '@contentstack/cli-utilities': ~1.15.0 '@oclif/core': ^4.3.0 @@ -533,12 +533,12 @@ importers: packages/contentstack-export: specifiers: '@contentstack/cli-auth': ~1.6.2 - '@contentstack/cli-command': ~1.7.0 + '@contentstack/cli-command': ~1.7.1 '@contentstack/cli-config': ~1.15.3 '@contentstack/cli-dev-dependencies': ~1.3.1 '@contentstack/cli-utilities': ~1.15.0 - '@contentstack/cli-variants': ~2.0.0-beta.3 - '@oclif/core': ^4.3.3 + '@contentstack/cli-variants': ~2.0.0-beta.4 + '@oclif/core': ^4.8.0 '@oclif/plugin-help': ^6.2.28 '@oclif/test': ^4.1.13 '@types/big-json': ^3.2.5 @@ -657,8 +657,8 @@ importers: '@contentstack/cli-audit': ~2.0.0-beta.1 '@contentstack/cli-command': ~1.7.0 '@contentstack/cli-utilities': ~1.15.0 - '@contentstack/cli-variants': ~2.0.0-beta.3 - '@contentstack/management': ~1.22.0 + '@contentstack/cli-variants': ~2.0.0-beta.4 + '@contentstack/management': ~1.27.2 '@oclif/core': ^4.3.0 '@oclif/test': ^4.1.13 '@types/big-json': ^3.2.5 @@ -696,7 +696,7 @@ importers: '@contentstack/cli-command': 1.7.1_lxq42tdpoxpye5tb7w3htdbbdq '@contentstack/cli-utilities': link:../contentstack-utilities '@contentstack/cli-variants': link:../contentstack-variants - '@contentstack/management': 1.22.0_debug@4.4.3 + '@contentstack/management': 1.27.2_debug@4.4.3 '@oclif/core': 4.8.0 big-json: 3.2.0 bluebird: 3.7.2 @@ -853,7 +853,7 @@ importers: packages/contentstack-seed: specifiers: - '@contentstack/cli-cm-import': ~2.0.0-beta.3 + '@contentstack/cli-cm-import': ~2.0.0-beta.4 '@contentstack/cli-command': ~1.7.0 '@contentstack/cli-utilities': ~1.15.0 '@contentstack/management': ~1.22.0 @@ -871,7 +871,7 @@ importers: jest: ^29.7.0 mkdirp: ^1.0.4 oclif: ^4.17.46 - tar: ^6.2.1 + tar: ^7.5.4 tmp: ^0.2.3 ts-jest: ^29.3.4 ts-node: ^8.10.2 @@ -883,7 +883,7 @@ importers: '@contentstack/management': 1.22.0 inquirer: 8.2.7_@types+node@14.18.63 mkdirp: 1.0.4 - tar: 6.2.1 + tar: 7.5.6 tmp: 0.2.5 devDependencies: '@types/inquirer': 9.0.9 @@ -952,7 +952,7 @@ importers: xdg-basedir: ^4.0.0 dependencies: '@contentstack/management': 1.25.1 - '@contentstack/marketplace-sdk': 1.4.1 + '@contentstack/marketplace-sdk': 1.4.2 '@oclif/core': 4.8.0 axios: 1.13.2 chalk: 4.1.2 @@ -1073,7 +1073,7 @@ packages: engines: {node: '>=16.0.0'} dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 tslib: 2.8.1 dev: true @@ -1081,7 +1081,7 @@ packages: resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 tslib: 2.8.1 dev: true @@ -1090,8 +1090,8 @@ packages: dependencies: '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.969.0 - '@aws-sdk/util-locate-window': 3.965.2 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-locate-window': 3.965.3 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 dev: true @@ -1102,8 +1102,8 @@ packages: '@aws-crypto/sha256-js': 5.2.0 '@aws-crypto/supports-web-crypto': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.969.0 - '@aws-sdk/util-locate-window': 3.965.2 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-locate-window': 3.965.3 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 dev: true @@ -1113,7 +1113,7 @@ packages: engines: {node: '>=16.0.0'} dependencies: '@aws-crypto/util': 5.2.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 tslib: 2.8.1 dev: true @@ -1126,49 +1126,49 @@ packages: /@aws-crypto/util/5.2.0: resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} dependencies: - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 '@smithy/util-utf8': 2.3.0 tslib: 2.8.1 dev: true - /@aws-sdk/client-cloudfront/3.971.0: - resolution: {integrity: sha512-kLtm5jaWVXaej8a6WbFd1iDMFXy19WakT8b/hk3gHtcm6KfnTGX1K/YwpNGfuTzUze16ZjQrbIen/loM+2U2KA==} + /@aws-sdk/client-cloudfront/3.972.0: + resolution: {integrity: sha512-mmFa46bKR6EE6RjdN+hM43GdHt7/RbHCpbuA5zBNbR4bKol7xGHIYemtLGuY0yinDshu5A0hzksulw51FnkUug==} engines: {node: '>=20.0.0'} dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.970.0 - '@aws-sdk/credential-provider-node': 3.971.0 - '@aws-sdk/middleware-host-header': 3.969.0 - '@aws-sdk/middleware-logger': 3.969.0 - '@aws-sdk/middleware-recursion-detection': 3.969.0 - '@aws-sdk/middleware-user-agent': 3.970.0 - '@aws-sdk/region-config-resolver': 3.969.0 - '@aws-sdk/types': 3.969.0 - '@aws-sdk/util-endpoints': 3.970.0 - '@aws-sdk/util-user-agent-browser': 3.969.0 - '@aws-sdk/util-user-agent-node': 3.971.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/credential-provider-node': 3.972.0 + '@aws-sdk/middleware-host-header': 3.972.0 + '@aws-sdk/middleware-logger': 3.972.0 + '@aws-sdk/middleware-recursion-detection': 3.972.0 + '@aws-sdk/middleware-user-agent': 3.972.0 + '@aws-sdk/region-config-resolver': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-endpoints': 3.972.0 + '@aws-sdk/util-user-agent-browser': 3.972.0 + '@aws-sdk/util-user-agent-node': 3.972.0 '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.20.7 + '@smithy/core': 3.21.0 '@smithy/fetch-http-handler': 5.3.9 '@smithy/hash-node': 4.2.8 '@smithy/invalid-dependency': 4.2.8 '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.8 - '@smithy/middleware-retry': 4.4.24 + '@smithy/middleware-endpoint': 4.4.10 + '@smithy/middleware-retry': 4.4.26 '@smithy/middleware-serde': 4.2.9 '@smithy/middleware-stack': 4.2.8 '@smithy/node-config-provider': 4.3.8 '@smithy/node-http-handler': 4.4.8 '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.10.9 + '@smithy/smithy-client': 4.10.11 '@smithy/types': 4.12.0 '@smithy/url-parser': 4.2.8 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.23 - '@smithy/util-defaults-mode-node': 4.2.26 + '@smithy/util-defaults-mode-browser': 4.3.25 + '@smithy/util-defaults-mode-node': 4.2.28 '@smithy/util-endpoints': 3.2.8 '@smithy/util-middleware': 4.2.8 '@smithy/util-retry': 4.2.8 @@ -1180,33 +1180,33 @@ packages: - aws-crt dev: true - /@aws-sdk/client-s3/3.971.0: - resolution: {integrity: sha512-BBUne390fKa4C4QvZlUZ5gKcu+Uyid4IyQ20N4jl0vS7SK2xpfXlJcgKqPW5ts6kx6hWTQBk6sH5Lf12RvuJxg==} + /@aws-sdk/client-s3/3.972.0: + resolution: {integrity: sha512-ghpDQtjZvbhbnHWymq/V5TL8NppdAGF2THAxYRRBLCJ5JRlq71T24NdovAzvzYaGdH7HtcRkgErBRsFT1gtq4g==} engines: {node: '>=20.0.0'} dependencies: '@aws-crypto/sha1-browser': 5.2.0 '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.970.0 - '@aws-sdk/credential-provider-node': 3.971.0 - '@aws-sdk/middleware-bucket-endpoint': 3.969.0 - '@aws-sdk/middleware-expect-continue': 3.969.0 - '@aws-sdk/middleware-flexible-checksums': 3.971.0 - '@aws-sdk/middleware-host-header': 3.969.0 - '@aws-sdk/middleware-location-constraint': 3.969.0 - '@aws-sdk/middleware-logger': 3.969.0 - '@aws-sdk/middleware-recursion-detection': 3.969.0 - '@aws-sdk/middleware-sdk-s3': 3.970.0 - '@aws-sdk/middleware-ssec': 3.971.0 - '@aws-sdk/middleware-user-agent': 3.970.0 - '@aws-sdk/region-config-resolver': 3.969.0 - '@aws-sdk/signature-v4-multi-region': 3.970.0 - '@aws-sdk/types': 3.969.0 - '@aws-sdk/util-endpoints': 3.970.0 - '@aws-sdk/util-user-agent-browser': 3.969.0 - '@aws-sdk/util-user-agent-node': 3.971.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/credential-provider-node': 3.972.0 + '@aws-sdk/middleware-bucket-endpoint': 3.972.0 + '@aws-sdk/middleware-expect-continue': 3.972.0 + '@aws-sdk/middleware-flexible-checksums': 3.972.0 + '@aws-sdk/middleware-host-header': 3.972.0 + '@aws-sdk/middleware-location-constraint': 3.972.0 + '@aws-sdk/middleware-logger': 3.972.0 + '@aws-sdk/middleware-recursion-detection': 3.972.0 + '@aws-sdk/middleware-sdk-s3': 3.972.0 + '@aws-sdk/middleware-ssec': 3.972.0 + '@aws-sdk/middleware-user-agent': 3.972.0 + '@aws-sdk/region-config-resolver': 3.972.0 + '@aws-sdk/signature-v4-multi-region': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-endpoints': 3.972.0 + '@aws-sdk/util-user-agent-browser': 3.972.0 + '@aws-sdk/util-user-agent-node': 3.972.0 '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.20.7 + '@smithy/core': 3.21.0 '@smithy/eventstream-serde-browser': 4.2.8 '@smithy/eventstream-serde-config-resolver': 4.3.8 '@smithy/eventstream-serde-node': 4.2.8 @@ -1217,21 +1217,21 @@ packages: '@smithy/invalid-dependency': 4.2.8 '@smithy/md5-js': 4.2.8 '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.8 - '@smithy/middleware-retry': 4.4.24 + '@smithy/middleware-endpoint': 4.4.10 + '@smithy/middleware-retry': 4.4.26 '@smithy/middleware-serde': 4.2.9 '@smithy/middleware-stack': 4.2.8 '@smithy/node-config-provider': 4.3.8 '@smithy/node-http-handler': 4.4.8 '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.10.9 + '@smithy/smithy-client': 4.10.11 '@smithy/types': 4.12.0 '@smithy/url-parser': 4.2.8 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.23 - '@smithy/util-defaults-mode-node': 4.2.26 + '@smithy/util-defaults-mode-browser': 4.3.25 + '@smithy/util-defaults-mode-node': 4.2.28 '@smithy/util-endpoints': 3.2.8 '@smithy/util-middleware': 4.2.8 '@smithy/util-retry': 4.2.8 @@ -1243,43 +1243,43 @@ packages: - aws-crt dev: true - /@aws-sdk/client-sso/3.971.0: - resolution: {integrity: sha512-Xx+w6DQqJxDdymYyIxyKJnRzPvVJ4e/Aw0czO7aC9L/iraaV7AG8QtRe93OGW6aoHSh72CIiinnpJJfLsQqP4g==} + /@aws-sdk/client-sso/3.972.0: + resolution: {integrity: sha512-5qw6qLiRE4SUiz0hWy878dSR13tSVhbTWhsvFT8mGHe37NRRiaobm5MA2sWD0deRAuO98djSiV+dhWXa1xIFNw==} engines: {node: '>=20.0.0'} dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.970.0 - '@aws-sdk/middleware-host-header': 3.969.0 - '@aws-sdk/middleware-logger': 3.969.0 - '@aws-sdk/middleware-recursion-detection': 3.969.0 - '@aws-sdk/middleware-user-agent': 3.970.0 - '@aws-sdk/region-config-resolver': 3.969.0 - '@aws-sdk/types': 3.969.0 - '@aws-sdk/util-endpoints': 3.970.0 - '@aws-sdk/util-user-agent-browser': 3.969.0 - '@aws-sdk/util-user-agent-node': 3.971.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/middleware-host-header': 3.972.0 + '@aws-sdk/middleware-logger': 3.972.0 + '@aws-sdk/middleware-recursion-detection': 3.972.0 + '@aws-sdk/middleware-user-agent': 3.972.0 + '@aws-sdk/region-config-resolver': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-endpoints': 3.972.0 + '@aws-sdk/util-user-agent-browser': 3.972.0 + '@aws-sdk/util-user-agent-node': 3.972.0 '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.20.7 + '@smithy/core': 3.21.0 '@smithy/fetch-http-handler': 5.3.9 '@smithy/hash-node': 4.2.8 '@smithy/invalid-dependency': 4.2.8 '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.8 - '@smithy/middleware-retry': 4.4.24 + '@smithy/middleware-endpoint': 4.4.10 + '@smithy/middleware-retry': 4.4.26 '@smithy/middleware-serde': 4.2.9 '@smithy/middleware-stack': 4.2.8 '@smithy/node-config-provider': 4.3.8 '@smithy/node-http-handler': 4.4.8 '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.10.9 + '@smithy/smithy-client': 4.10.11 '@smithy/types': 4.12.0 '@smithy/url-parser': 4.2.8 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.23 - '@smithy/util-defaults-mode-node': 4.2.26 + '@smithy/util-defaults-mode-browser': 4.3.25 + '@smithy/util-defaults-mode-node': 4.2.28 '@smithy/util-endpoints': 3.2.8 '@smithy/util-middleware': 4.2.8 '@smithy/util-retry': 4.2.8 @@ -1289,18 +1289,18 @@ packages: - aws-crt dev: true - /@aws-sdk/core/3.970.0: - resolution: {integrity: sha512-klpzObldOq8HXzDjDlY6K8rMhYZU6mXRz6P9F9N+tWnjoYFfeBMra8wYApydElTUYQKP1O7RLHwH1OKFfKcqIA==} + /@aws-sdk/core/3.972.0: + resolution: {integrity: sha512-nEeUW2M9F+xdIaD98F5MBcQ4ITtykj3yKbgFZ6J0JtL3bq+Z90szQ6Yy8H/BLPYXTs3V4n9ifnBo8cprRDiE6A==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/types': 3.969.0 - '@aws-sdk/xml-builder': 3.969.0 - '@smithy/core': 3.20.7 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/xml-builder': 3.972.0 + '@smithy/core': 3.21.0 '@smithy/node-config-provider': 4.3.8 '@smithy/property-provider': 4.2.8 '@smithy/protocol-http': 5.3.8 '@smithy/signature-v4': 5.3.8 - '@smithy/smithy-client': 4.10.9 + '@smithy/smithy-client': 4.10.11 '@smithy/types': 4.12.0 '@smithy/util-base64': 4.3.0 '@smithy/util-middleware': 4.2.8 @@ -1308,54 +1308,54 @@ packages: tslib: 2.8.1 dev: true - /@aws-sdk/crc64-nvme/3.969.0: - resolution: {integrity: sha512-IGNkP54HD3uuLnrPCYsv3ZD478UYq+9WwKrIVJ9Pdi3hxPg8562CH3ZHf8hEgfePN31P9Kj+Zu9kq2Qcjjt61A==} + /@aws-sdk/crc64-nvme/3.972.0: + resolution: {integrity: sha512-ThlLhTqX68jvoIVv+pryOdb5coP1cX1/MaTbB9xkGDCbWbsqQcLqzPxuSoW1DCnAAIacmXCWpzUNOB9pv+xXQw==} engines: {node: '>=20.0.0'} dependencies: '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/credential-provider-env/3.970.0: - resolution: {integrity: sha512-rtVzXzEtAfZBfh+lq3DAvRar4c3jyptweOAJR2DweyXx71QSMY+O879hjpMwES7jl07a3O1zlnFIDo4KP/96kQ==} + /@aws-sdk/credential-provider-env/3.972.0: + resolution: {integrity: sha512-kKHoNv+maHlPQOAhYamhap0PObd16SAb3jwaY0KYgNTiSbeXlbGUZPLioo9oA3wU10zItJzx83ClU7d7h40luA==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/core': 3.970.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/property-provider': 4.2.8 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/credential-provider-http/3.970.0: - resolution: {integrity: sha512-CjDbWL7JxjLc9ZxQilMusWSw05yRvUJKRpz59IxDpWUnSMHC9JMMUUkOy5Izk8UAtzi6gupRWArp4NG4labt9Q==} + /@aws-sdk/credential-provider-http/3.972.0: + resolution: {integrity: sha512-xzEi81L7I5jGUbpmqEHCe7zZr54hCABdj4H+3LzktHYuovV/oqnvoDdvZpGFR0e/KAw1+PL38NbGrpG30j6qlA==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/core': 3.970.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/fetch-http-handler': 5.3.9 '@smithy/node-http-handler': 4.4.8 '@smithy/property-provider': 4.2.8 '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.10.9 + '@smithy/smithy-client': 4.10.11 '@smithy/types': 4.12.0 '@smithy/util-stream': 4.5.10 tslib: 2.8.1 dev: true - /@aws-sdk/credential-provider-ini/3.971.0: - resolution: {integrity: sha512-c0TGJG4xyfTZz3SInXfGU8i5iOFRrLmy4Bo7lMyH+IpngohYMYGYl61omXqf2zdwMbDv+YJ9AviQTcCaEUKi8w==} + /@aws-sdk/credential-provider-ini/3.972.0: + resolution: {integrity: sha512-ruhAMceUIq2aknFd3jhWxmO0P0Efab5efjyIXOkI9i80g+zDY5VekeSxfqRKStEEJSKSCHDLQuOu0BnAn4Rzew==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/core': 3.970.0 - '@aws-sdk/credential-provider-env': 3.970.0 - '@aws-sdk/credential-provider-http': 3.970.0 - '@aws-sdk/credential-provider-login': 3.971.0 - '@aws-sdk/credential-provider-process': 3.970.0 - '@aws-sdk/credential-provider-sso': 3.971.0 - '@aws-sdk/credential-provider-web-identity': 3.971.0 - '@aws-sdk/nested-clients': 3.971.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/credential-provider-env': 3.972.0 + '@aws-sdk/credential-provider-http': 3.972.0 + '@aws-sdk/credential-provider-login': 3.972.0 + '@aws-sdk/credential-provider-process': 3.972.0 + '@aws-sdk/credential-provider-sso': 3.972.0 + '@aws-sdk/credential-provider-web-identity': 3.972.0 + '@aws-sdk/nested-clients': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/credential-provider-imds': 4.2.8 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 @@ -1365,13 +1365,13 @@ packages: - aws-crt dev: true - /@aws-sdk/credential-provider-login/3.971.0: - resolution: {integrity: sha512-yhbzmDOsk0RXD3rTPhZra4AWVnVAC4nFWbTp+sUty1hrOPurUmhuz8bjpLqYTHGnlMbJp+UqkQONhS2+2LzW2g==} + /@aws-sdk/credential-provider-login/3.972.0: + resolution: {integrity: sha512-SsrsFJsEYAJHO4N/r2P0aK6o8si6f1lprR+Ej8J731XJqTckSGs/HFHcbxOyW/iKt+LNUvZa59/VlJmjhF4bEQ==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/core': 3.970.0 - '@aws-sdk/nested-clients': 3.971.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/nested-clients': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/property-provider': 4.2.8 '@smithy/protocol-http': 5.3.8 '@smithy/shared-ini-file-loader': 4.4.3 @@ -1381,17 +1381,17 @@ packages: - aws-crt dev: true - /@aws-sdk/credential-provider-node/3.971.0: - resolution: {integrity: sha512-epUJBAKivtJqalnEBRsYIULKYV063o/5mXNJshZfyvkAgNIzc27CmmKRXTN4zaNOZg8g/UprFp25BGsi19x3nQ==} + /@aws-sdk/credential-provider-node/3.972.0: + resolution: {integrity: sha512-wwJDpEGl6+sOygic8QKu0OHVB8SiodqF1fr5jvUlSFfS6tJss/E9vBc2aFjl7zI6KpAIYfIzIgM006lRrZtWCQ==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/credential-provider-env': 3.970.0 - '@aws-sdk/credential-provider-http': 3.970.0 - '@aws-sdk/credential-provider-ini': 3.971.0 - '@aws-sdk/credential-provider-process': 3.970.0 - '@aws-sdk/credential-provider-sso': 3.971.0 - '@aws-sdk/credential-provider-web-identity': 3.971.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/credential-provider-env': 3.972.0 + '@aws-sdk/credential-provider-http': 3.972.0 + '@aws-sdk/credential-provider-ini': 3.972.0 + '@aws-sdk/credential-provider-process': 3.972.0 + '@aws-sdk/credential-provider-sso': 3.972.0 + '@aws-sdk/credential-provider-web-identity': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/credential-provider-imds': 4.2.8 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 @@ -1401,26 +1401,26 @@ packages: - aws-crt dev: true - /@aws-sdk/credential-provider-process/3.970.0: - resolution: {integrity: sha512-0XeT8OaT9iMA62DFV9+m6mZfJhrD0WNKf4IvsIpj2Z7XbaYfz3CoDDvNoALf3rPY9NzyMHgDxOspmqdvXP00mw==} + /@aws-sdk/credential-provider-process/3.972.0: + resolution: {integrity: sha512-nmzYhamLDJ8K+v3zWck79IaKMc350xZnWsf/GeaXO6E3MewSzd3lYkTiMi7lEp3/UwDm9NHfPguoPm+mhlSWQQ==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/core': 3.970.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/credential-provider-sso/3.971.0: - resolution: {integrity: sha512-dY0hMQ7dLVPQNJ8GyqXADxa9w5wNfmukgQniLxGVn+dMRx3YLViMp5ZpTSQpFhCWNF0oKQrYAI5cHhUJU1hETw==} + /@aws-sdk/credential-provider-sso/3.972.0: + resolution: {integrity: sha512-6mYyfk1SrMZ15cH9T53yAF4YSnvq4yU1Xlgm3nqV1gZVQzmF5kr4t/F3BU3ygbvzi4uSwWxG3I3TYYS5eMlAyg==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/client-sso': 3.971.0 - '@aws-sdk/core': 3.970.0 - '@aws-sdk/token-providers': 3.971.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/client-sso': 3.972.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/token-providers': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 '@smithy/types': 4.12.0 @@ -1429,13 +1429,13 @@ packages: - aws-crt dev: true - /@aws-sdk/credential-provider-web-identity/3.971.0: - resolution: {integrity: sha512-F1AwfNLr7H52T640LNON/h34YDiMuIqW/ZreGzhRR6vnFGaSPtNSKAKB2ssAMkLM8EVg8MjEAYD3NCUiEo+t/w==} + /@aws-sdk/credential-provider-web-identity/3.972.0: + resolution: {integrity: sha512-vsJXBGL8H54kz4T6do3p5elATj5d1izVGUXMluRJntm9/I0be/zUYtdd4oDTM2kSUmd4Zhyw3fMQ9lw7CVhd4A==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/core': 3.970.0 - '@aws-sdk/nested-clients': 3.971.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/nested-clients': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 '@smithy/types': 4.12.0 @@ -1444,12 +1444,12 @@ packages: - aws-crt dev: true - /@aws-sdk/middleware-bucket-endpoint/3.969.0: - resolution: {integrity: sha512-MlbrlixtkTVhYhoasblKOkr7n2yydvUZjjxTnBhIuHmkyBS1619oGnTfq/uLeGYb4NYXdeQ5OYcqsRGvmWSuTw==} + /@aws-sdk/middleware-bucket-endpoint/3.972.0: + resolution: {integrity: sha512-IrIjAehc3PrseAGfk2ldtAf+N0BAnNHR1DCZIDh9IAcFrTVWC3Fi9KJdtabrxcY3Onpt/8opOco4EIEAWgMz7A==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/types': 3.969.0 - '@aws-sdk/util-arn-parser': 3.968.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-arn-parser': 3.972.0 '@smithy/node-config-provider': 4.3.8 '@smithy/protocol-http': 5.3.8 '@smithy/types': 4.12.0 @@ -1457,26 +1457,26 @@ packages: tslib: 2.8.1 dev: true - /@aws-sdk/middleware-expect-continue/3.969.0: - resolution: {integrity: sha512-qXygzSi8osok7tH9oeuS3HoKw6jRfbvg5Me/X5RlHOvSSqQz8c5O9f3MjUApaCUSwbAU92KrbZWasw2PKiaVHg==} + /@aws-sdk/middleware-expect-continue/3.972.0: + resolution: {integrity: sha512-xyhDoY0qse8MvQC4RZCpT5WoIQ4/kwqv71Dh1s3mdXjL789Z4a6L/khBTSXECR5+egSZ960AInj3aR+CrezDRQ==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 '@smithy/protocol-http': 5.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/middleware-flexible-checksums/3.971.0: - resolution: {integrity: sha512-+hGUDUxeIw8s2kkjfeXym0XZxdh0cqkHkDpEanWYdS1gnWkIR+gf9u/DKbKqGHXILPaqHXhWpLTQTVlaB4sI7Q==} + /@aws-sdk/middleware-flexible-checksums/3.972.0: + resolution: {integrity: sha512-zxK0ezmT7fLEPJ650S8QBc4rGDq5+5rdsLnnuZ6hPaZE4/+QtUoTw+gSDETyiWodNcRuz2ZWnqi17K+7nKtSRg==} engines: {node: '>=20.0.0'} dependencies: '@aws-crypto/crc32': 5.2.0 '@aws-crypto/crc32c': 5.2.0 '@aws-crypto/util': 5.2.0 - '@aws-sdk/core': 3.970.0 - '@aws-sdk/crc64-nvme': 3.969.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/crc64-nvme': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/is-array-buffer': 4.2.0 '@smithy/node-config-provider': 4.3.8 '@smithy/protocol-http': 5.3.8 @@ -1487,57 +1487,57 @@ packages: tslib: 2.8.1 dev: true - /@aws-sdk/middleware-host-header/3.969.0: - resolution: {integrity: sha512-AWa4rVsAfBR4xqm7pybQ8sUNJYnjyP/bJjfAw34qPuh3M9XrfGbAHG0aiAfQGrBnmS28jlO6Kz69o+c6PRw1dw==} + /@aws-sdk/middleware-host-header/3.972.0: + resolution: {integrity: sha512-3eztFI6F9/eHtkIaWKN3nT+PM+eQ6p1MALDuNshFk323ixuCZzOOVT8oUqtZa30Z6dycNXJwhlIq7NhUVFfimw==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 '@smithy/protocol-http': 5.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/middleware-location-constraint/3.969.0: - resolution: {integrity: sha512-zH7pDfMLG/C4GWMOpvJEoYcSpj7XsNP9+irlgqwi667sUQ6doHQJ3yyDut3yiTk0maq1VgmriPFELyI9lrvH/g==} + /@aws-sdk/middleware-location-constraint/3.972.0: + resolution: {integrity: sha512-WpsxoVPzbGPQGb/jupNYjpE0REcCPtjz7Q7zAt+dyo7fxsLBn4J+Rp6AYzSa04J9VrmrvCqCbVLu6B88PlSKSQ==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/middleware-logger/3.969.0: - resolution: {integrity: sha512-xwrxfip7Y2iTtCMJ+iifN1E1XMOuhxIHY9DreMCvgdl4r7+48x2S1bCYPWH3eNY85/7CapBWdJ8cerpEl12sQQ==} + /@aws-sdk/middleware-logger/3.972.0: + resolution: {integrity: sha512-ZvdyVRwzK+ra31v1pQrgbqR/KsLD+wwJjHgko6JfoKUBIcEfAwJzQKO6HspHxdHWTVUz6MgvwskheR/TTYZl2g==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/middleware-recursion-detection/3.969.0: - resolution: {integrity: sha512-2r3PuNquU3CcS1Am4vn/KHFwLi8QFjMdA/R+CRDXT4AFO/0qxevF/YStW3gAKntQIgWgQV8ZdEtKAoJvLI4UWg==} + /@aws-sdk/middleware-recursion-detection/3.972.0: + resolution: {integrity: sha512-F2SmUeO+S6l1h6dydNet3BQIk173uAkcfU1HDkw/bUdRLAnh15D3HP9vCZ7oCPBNcdEICbXYDmx0BR9rRUHGlQ==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 '@aws/lambda-invoke-store': 0.2.3 '@smithy/protocol-http': 5.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/middleware-sdk-s3/3.970.0: - resolution: {integrity: sha512-v/Y5F1lbFFY7vMeG5yYxuhnn0CAshz6KMxkz1pDyPxejNE9HtA0w8R6OTBh/bVdIm44QpjhbI7qeLdOE/PLzXQ==} + /@aws-sdk/middleware-sdk-s3/3.972.0: + resolution: {integrity: sha512-0bcKFXWx+NZ7tIlOo7KjQ+O2rydiHdIQahrq+fN6k9Osky29v17guy68urUKfhTobR6iY6KvxkroFWaFtTgS5w==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/core': 3.970.0 - '@aws-sdk/types': 3.969.0 - '@aws-sdk/util-arn-parser': 3.968.0 - '@smithy/core': 3.20.7 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-arn-parser': 3.972.0 + '@smithy/core': 3.21.0 '@smithy/node-config-provider': 4.3.8 '@smithy/protocol-http': 5.3.8 '@smithy/signature-v4': 5.3.8 - '@smithy/smithy-client': 4.10.9 + '@smithy/smithy-client': 4.10.11 '@smithy/types': 4.12.0 '@smithy/util-config-provider': 4.2.0 '@smithy/util-middleware': 4.2.8 @@ -1546,65 +1546,65 @@ packages: tslib: 2.8.1 dev: true - /@aws-sdk/middleware-ssec/3.971.0: - resolution: {integrity: sha512-QGVhvRveYG64ZhnS/b971PxXM6N2NU79Fxck4EfQ7am8v1Br0ctoeDDAn9nXNblLGw87we9Z65F7hMxxiFHd3w==} + /@aws-sdk/middleware-ssec/3.972.0: + resolution: {integrity: sha512-cEr2HtK4R2fi8Y0P95cjbr4KJOjKBt8ms95mEJhabJN8KM4CpD4iS/J1lhvMj+qWir0KBTV6gKmxECXdfL9S6w==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/middleware-user-agent/3.970.0: - resolution: {integrity: sha512-dnSJGGUGSFGEX2NzvjwSefH+hmZQ347AwbLhAsi0cdnISSge+pcGfOFrJt2XfBIypwFe27chQhlfuf/gWdzpZg==} + /@aws-sdk/middleware-user-agent/3.972.0: + resolution: {integrity: sha512-kFHQm2OCBJCzGWRafgdWHGFjitUXY/OxXngymcX4l8CiyiNDZB27HDDBg2yLj3OUJc4z4fexLMmP8r9vgag19g==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/core': 3.970.0 - '@aws-sdk/types': 3.969.0 - '@aws-sdk/util-endpoints': 3.970.0 - '@smithy/core': 3.20.7 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-endpoints': 3.972.0 + '@smithy/core': 3.21.0 '@smithy/protocol-http': 5.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/nested-clients/3.971.0: - resolution: {integrity: sha512-TWaILL8GyYlhGrxxnmbkazM4QsXatwQgoWUvo251FXmUOsiXDFDVX3hoGIfB3CaJhV2pJPfebHUNJtY6TjZ11g==} + /@aws-sdk/nested-clients/3.972.0: + resolution: {integrity: sha512-QGlbnuGzSQJVG6bR9Qw6G0Blh6abFR4VxNa61ttMbzy9jt28xmk2iGtrYLrQPlCCPhY6enHqjTWm3n3LOb0wAw==} engines: {node: '>=20.0.0'} dependencies: '@aws-crypto/sha256-browser': 5.2.0 '@aws-crypto/sha256-js': 5.2.0 - '@aws-sdk/core': 3.970.0 - '@aws-sdk/middleware-host-header': 3.969.0 - '@aws-sdk/middleware-logger': 3.969.0 - '@aws-sdk/middleware-recursion-detection': 3.969.0 - '@aws-sdk/middleware-user-agent': 3.970.0 - '@aws-sdk/region-config-resolver': 3.969.0 - '@aws-sdk/types': 3.969.0 - '@aws-sdk/util-endpoints': 3.970.0 - '@aws-sdk/util-user-agent-browser': 3.969.0 - '@aws-sdk/util-user-agent-node': 3.971.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/middleware-host-header': 3.972.0 + '@aws-sdk/middleware-logger': 3.972.0 + '@aws-sdk/middleware-recursion-detection': 3.972.0 + '@aws-sdk/middleware-user-agent': 3.972.0 + '@aws-sdk/region-config-resolver': 3.972.0 + '@aws-sdk/types': 3.972.0 + '@aws-sdk/util-endpoints': 3.972.0 + '@aws-sdk/util-user-agent-browser': 3.972.0 + '@aws-sdk/util-user-agent-node': 3.972.0 '@smithy/config-resolver': 4.4.6 - '@smithy/core': 3.20.7 + '@smithy/core': 3.21.0 '@smithy/fetch-http-handler': 5.3.9 '@smithy/hash-node': 4.2.8 '@smithy/invalid-dependency': 4.2.8 '@smithy/middleware-content-length': 4.2.8 - '@smithy/middleware-endpoint': 4.4.8 - '@smithy/middleware-retry': 4.4.24 + '@smithy/middleware-endpoint': 4.4.10 + '@smithy/middleware-retry': 4.4.26 '@smithy/middleware-serde': 4.2.9 '@smithy/middleware-stack': 4.2.8 '@smithy/node-config-provider': 4.3.8 '@smithy/node-http-handler': 4.4.8 '@smithy/protocol-http': 5.3.8 - '@smithy/smithy-client': 4.10.9 + '@smithy/smithy-client': 4.10.11 '@smithy/types': 4.12.0 '@smithy/url-parser': 4.2.8 '@smithy/util-base64': 4.3.0 '@smithy/util-body-length-browser': 4.2.0 '@smithy/util-body-length-node': 4.2.1 - '@smithy/util-defaults-mode-browser': 4.3.23 - '@smithy/util-defaults-mode-node': 4.2.26 + '@smithy/util-defaults-mode-browser': 4.3.25 + '@smithy/util-defaults-mode-node': 4.2.28 '@smithy/util-endpoints': 3.2.8 '@smithy/util-middleware': 4.2.8 '@smithy/util-retry': 4.2.8 @@ -1614,36 +1614,36 @@ packages: - aws-crt dev: true - /@aws-sdk/region-config-resolver/3.969.0: - resolution: {integrity: sha512-scj9OXqKpcjJ4jsFLtqYWz3IaNvNOQTFFvEY8XMJXTv+3qF5I7/x9SJtKzTRJEBF3spjzBUYPtGFbs9sj4fisQ==} + /@aws-sdk/region-config-resolver/3.972.0: + resolution: {integrity: sha512-JyOf+R/6vJW8OEVFCAyzEOn2reri/Q+L0z9zx4JQSKWvTmJ1qeFO25sOm8VIfB8URKhfGRTQF30pfYaH2zxt/A==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 '@smithy/config-resolver': 4.4.6 '@smithy/node-config-provider': 4.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/signature-v4-multi-region/3.970.0: - resolution: {integrity: sha512-z3syXfuK/x/IsKf/AeYmgc2NT7fcJ+3fHaGO+fkghkV9WEba3fPyOwtTBX4KpFMNb2t50zDGZwbzW1/5ighcUQ==} + /@aws-sdk/signature-v4-multi-region/3.972.0: + resolution: {integrity: sha512-2udiRijmjpN81Pvajje4TsjbXDZNP6K9bYUanBYH8hXa/tZG5qfGCySD+TyX0sgDxCQmEDMg3LaQdfjNHBDEgQ==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/middleware-sdk-s3': 3.970.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/middleware-sdk-s3': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/protocol-http': 5.3.8 '@smithy/signature-v4': 5.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/token-providers/3.971.0: - resolution: {integrity: sha512-4hKGWZbmuDdONMJV0HJ+9jwTDb0zLfKxcCLx2GEnBY31Gt9GeyIQ+DZ97Bb++0voawj6pnZToFikXTyrEq2x+w==} + /@aws-sdk/token-providers/3.972.0: + resolution: {integrity: sha512-kWlXG+y5nZhgXGEtb72Je+EvqepBPs8E3vZse//1PYLWs2speFqbGE/ywCXmzEJgHgVqSB/u/lqBvs5WlYmSqQ==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/core': 3.970.0 - '@aws-sdk/nested-clients': 3.971.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/core': 3.972.0 + '@aws-sdk/nested-clients': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/property-provider': 4.2.8 '@smithy/shared-ini-file-loader': 4.4.3 '@smithy/types': 4.12.0 @@ -1652,50 +1652,50 @@ packages: - aws-crt dev: true - /@aws-sdk/types/3.969.0: - resolution: {integrity: sha512-7IIzM5TdiXn+VtgPdVLjmE6uUBUtnga0f4RiSEI1WW10RPuNvZ9U+pL3SwDiRDAdoGrOF9tSLJOFZmfuwYuVYQ==} + /@aws-sdk/types/3.972.0: + resolution: {integrity: sha512-U7xBIbLSetONxb2bNzHyDgND3oKGoIfmknrEVnoEU4GUSs+0augUOIn9DIWGUO2ETcRFdsRUnmx9KhPT9Ojbug==} engines: {node: '>=20.0.0'} dependencies: '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/util-arn-parser/3.968.0: - resolution: {integrity: sha512-gqqvYcitIIM2K4lrDX9de9YvOfXBcVdxfT/iLnvHJd4YHvSXlt+gs+AsL4FfPCxG4IG9A+FyulP9Sb1MEA75vw==} + /@aws-sdk/util-arn-parser/3.972.0: + resolution: {integrity: sha512-RM5Mmo/KJ593iMSrALlHEOcc9YOIyOsDmS5x2NLOMdEmzv1o00fcpAkCQ02IGu1eFneBFT7uX0Mpag0HI+Cz2g==} engines: {node: '>=20.0.0'} dependencies: tslib: 2.8.1 dev: true - /@aws-sdk/util-endpoints/3.970.0: - resolution: {integrity: sha512-TZNZqFcMUtjvhZoZRtpEGQAdULYiy6rcGiXAbLU7e9LSpIYlRqpLa207oMNfgbzlL2PnHko+eVg8rajDiSOYCg==} + /@aws-sdk/util-endpoints/3.972.0: + resolution: {integrity: sha512-6JHsl1V/a1ZW8D8AFfd4R52fwZPnZ5H4U6DS8m/bWT8qad72NvbOFAC7U2cDtFs2TShqUO3TEiX/EJibtY3ijg==} engines: {node: '>=20.0.0'} dependencies: - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 '@smithy/types': 4.12.0 '@smithy/url-parser': 4.2.8 '@smithy/util-endpoints': 3.2.8 tslib: 2.8.1 dev: true - /@aws-sdk/util-locate-window/3.965.2: - resolution: {integrity: sha512-qKgO7wAYsXzhwCHhdbaKFyxd83Fgs8/1Ka+jjSPrv2Ll7mB55Wbwlo0kkfMLh993/yEc8aoDIAc1Fz9h4Spi4Q==} + /@aws-sdk/util-locate-window/3.965.3: + resolution: {integrity: sha512-FNUqAjlKAGA7GM05kywE99q8wiPHPZqrzhq3wXRga6PRD6A0kzT85Pb0AzYBVTBRpSrKyyr6M92Y6bnSBVp2BA==} engines: {node: '>=20.0.0'} dependencies: tslib: 2.8.1 dev: true - /@aws-sdk/util-user-agent-browser/3.969.0: - resolution: {integrity: sha512-bpJGjuKmFr0rA6UKUCmN8D19HQFMLXMx5hKBXqBlPFdalMhxJSjcxzX9DbQh0Fn6bJtxCguFmRGOBdQqNOt49g==} + /@aws-sdk/util-user-agent-browser/3.972.0: + resolution: {integrity: sha512-eOLdkQyoRbDgioTS3Orr7iVsVEutJyMZxvyZ6WAF95IrF0kfWx5Rd/KXnfbnG/VKa2CvjZiitWfouLzfVEyvJA==} dependencies: - '@aws-sdk/types': 3.969.0 + '@aws-sdk/types': 3.972.0 '@smithy/types': 4.12.0 bowser: 2.13.1 tslib: 2.8.1 dev: true - /@aws-sdk/util-user-agent-node/3.971.0: - resolution: {integrity: sha512-Eygjo9mFzQYjbGY3MYO6CsIhnTwAMd3WmuFalCykqEmj2r5zf0leWrhPaqvA5P68V5JdGfPYgj7vhNOd6CtRBQ==} + /@aws-sdk/util-user-agent-node/3.972.0: + resolution: {integrity: sha512-GOy+AiSrE9kGiojiwlZvVVSXwylu4+fmP0MJfvras/MwP09RB/YtQuOVR1E0fKQc6OMwaTNBjgAbOEhxuWFbAw==} engines: {node: '>=20.0.0'} peerDependencies: aws-crt: '>=1.0.0' @@ -1703,15 +1703,15 @@ packages: aws-crt: optional: true dependencies: - '@aws-sdk/middleware-user-agent': 3.970.0 - '@aws-sdk/types': 3.969.0 + '@aws-sdk/middleware-user-agent': 3.972.0 + '@aws-sdk/types': 3.972.0 '@smithy/node-config-provider': 4.3.8 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@aws-sdk/xml-builder/3.969.0: - resolution: {integrity: sha512-BSe4Lx/qdRQQdX8cSSI7Et20vqBspzAjBy8ZmXVoyLkol3y4sXBXzn+BiLtR+oh60ExQn6o2DU4QjdOZbXaKIQ==} + /@aws-sdk/xml-builder/3.972.0: + resolution: {integrity: sha512-POaGMcXnozzqBUyJM3HLUZ9GR6OKJWPGJEmhtTnxZXt8B6JcJ/6K3xRJ5H/j8oovVLz8Wg6vFxAHv8lvuASxMg==} engines: {node: '>=20.0.0'} dependencies: '@smithy/types': 4.12.0 @@ -2098,12 +2098,12 @@ packages: - debug dev: false - /@contentstack/cli-cm-bulk-publish/1.10.4_lxq42tdpoxpye5tb7w3htdbbdq: - resolution: {integrity: sha512-aatQnm/XBMTqa4fOFyHOuF8/IAadCm9MWi855x3xtGYxCwzTUnvcjvAZ2TLZH/v8qjv6JYa5Gzh4xouVofM6UQ==} + /@contentstack/cli-cm-bulk-publish/1.10.5_lxq42tdpoxpye5tb7w3htdbbdq: + resolution: {integrity: sha512-UYhLEKZTA0d2mPvNgLdKDIV+4NWiz6lv49wOKOlqQu77Lohf2mbrGMGVhtL8bq3zqBd7FBK3ng7QEDw6RHNG/w==} engines: {node: '>=14.0.0'} dependencies: '@contentstack/cli-command': 1.7.1_lxq42tdpoxpye5tb7w3htdbbdq - '@contentstack/cli-config': 1.16.2_lxq42tdpoxpye5tb7w3htdbbdq + '@contentstack/cli-config': 1.17.0_lxq42tdpoxpye5tb7w3htdbbdq '@contentstack/cli-utilities': 1.16.0_lxq42tdpoxpye5tb7w3htdbbdq '@oclif/core': 4.8.0 '@oclif/plugin-help': 6.2.36 @@ -2222,6 +2222,20 @@ packages: - debug dev: false + /@contentstack/cli-config/1.17.0_lxq42tdpoxpye5tb7w3htdbbdq: + resolution: {integrity: sha512-OW0ThVjabSQGSzHUJYLQANfR2ym6QNbyjb+zQV/5IezLITyrA6YZN7Iot1EZeMN3H14hm5GUjYKyx7KBbUKBqg==} + engines: {node: '>=14.0.0'} + dependencies: + '@contentstack/cli-command': 1.7.1_lxq42tdpoxpye5tb7w3htdbbdq + '@contentstack/cli-utilities': 1.16.0_lxq42tdpoxpye5tb7w3htdbbdq + '@oclif/core': 4.8.0 + '@oclif/plugin-help': 6.2.36 + lodash: 4.17.21 + transitivePeerDependencies: + - '@types/node' + - debug + dev: false + /@contentstack/cli-launch/1.9.3_ye7kx5d2fkdihvpgkysaadv2ca: resolution: {integrity: sha512-sSaZnxHDiFZjbzEFhFDIT9dvW/6rAXSKS8RO4TsoJk/ed2noUN4gVarAmAZt2B7qy7ICoPoXREIVOqi6FbaZqQ==} engines: {node: '>=14.0.0'} @@ -2233,10 +2247,10 @@ packages: '@oclif/core': 4.8.0 '@oclif/plugin-help': 6.2.36 '@oclif/plugin-plugins': 5.4.54 - '@rollup/plugin-commonjs': 28.0.9_rollup@4.55.1 - '@rollup/plugin-json': 6.1.0_rollup@4.55.1 - '@rollup/plugin-node-resolve': 16.0.3_rollup@4.55.1 - '@rollup/plugin-typescript': 12.3.0_5ruxaqqe36fu6wuhs7btsktcwq + '@rollup/plugin-commonjs': 28.0.9_rollup@4.55.3 + '@rollup/plugin-json': 6.1.0_rollup@4.55.3 + '@rollup/plugin-node-resolve': 16.0.3_rollup@4.55.3 + '@rollup/plugin-typescript': 12.3.0_4rny3w3kvl665dbmrblgq4incy '@types/express': 4.17.25 '@types/express-serve-static-core': 4.19.8 adm-zip: 0.5.16 @@ -2249,7 +2263,7 @@ packages: ini: 3.0.1 lodash: 4.17.21 open: 8.4.2 - rollup: 4.55.1 + rollup: 4.55.3 winston: 3.19.0 transitivePeerDependencies: - '@types/node' @@ -2269,7 +2283,7 @@ packages: resolution: {integrity: sha512-Q3csEjZk7rdEvbhRyq41jMT9nFduxR7zVpyGAkYdialh4KjMHxJvzVUdmYuA3PA92xoTlFdcY97yXPQJpmptTw==} dependencies: '@contentstack/management': 1.22.0 - '@contentstack/marketplace-sdk': 1.4.1 + '@contentstack/marketplace-sdk': 1.4.2 '@oclif/core': 4.8.0 axios: 1.13.2 chalk: 4.1.2 @@ -2304,7 +2318,7 @@ packages: resolution: {integrity: sha512-Q3csEjZk7rdEvbhRyq41jMT9nFduxR7zVpyGAkYdialh4KjMHxJvzVUdmYuA3PA92xoTlFdcY97yXPQJpmptTw==} dependencies: '@contentstack/management': 1.22.0_debug@4.4.3 - '@contentstack/marketplace-sdk': 1.4.1_debug@4.4.3 + '@contentstack/marketplace-sdk': 1.4.2_debug@4.4.3 '@oclif/core': 4.8.0 axios: 1.13.2_debug@4.4.3 chalk: 4.1.2 @@ -2340,7 +2354,7 @@ packages: resolution: {integrity: sha512-2SlKE9bJH3bd+ESNq1c9FWRCYzIjuWxRtXp+83eX7qDzHA7Lgu2EsRjfq+TcYVtBdCd0BzVATRIU2t/vNUl5Zw==} dependencies: '@contentstack/management': 1.25.1 - '@contentstack/marketplace-sdk': 1.4.1 + '@contentstack/marketplace-sdk': 1.4.2 '@oclif/core': 4.8.0 axios: 1.13.2 chalk: 4.1.2 @@ -2376,7 +2390,7 @@ packages: resolution: {integrity: sha512-2SlKE9bJH3bd+ESNq1c9FWRCYzIjuWxRtXp+83eX7qDzHA7Lgu2EsRjfq+TcYVtBdCd0BzVATRIU2t/vNUl5Zw==} dependencies: '@contentstack/management': 1.25.1 - '@contentstack/marketplace-sdk': 1.4.1 + '@contentstack/marketplace-sdk': 1.4.2 '@oclif/core': 4.8.0 axios: 1.13.2 chalk: 4.1.2 @@ -2413,7 +2427,7 @@ packages: resolution: {integrity: sha512-2SlKE9bJH3bd+ESNq1c9FWRCYzIjuWxRtXp+83eX7qDzHA7Lgu2EsRjfq+TcYVtBdCd0BzVATRIU2t/vNUl5Zw==} dependencies: '@contentstack/management': 1.25.1_debug@4.4.3 - '@contentstack/marketplace-sdk': 1.4.1_debug@4.4.3 + '@contentstack/marketplace-sdk': 1.4.2_debug@4.4.3 '@oclif/core': 4.8.0 axios: 1.13.2_debug@4.4.3 chalk: 4.1.2 @@ -2450,7 +2464,7 @@ packages: resolution: {integrity: sha512-2SlKE9bJH3bd+ESNq1c9FWRCYzIjuWxRtXp+83eX7qDzHA7Lgu2EsRjfq+TcYVtBdCd0BzVATRIU2t/vNUl5Zw==} dependencies: '@contentstack/management': 1.25.1_debug@4.4.3 - '@contentstack/marketplace-sdk': 1.4.1_debug@4.4.3 + '@contentstack/marketplace-sdk': 1.4.2_debug@4.4.3 '@oclif/core': 4.8.0 axios: 1.13.2_debug@4.4.3 chalk: 4.1.2 @@ -2547,15 +2561,35 @@ packages: - debug dev: false - /@contentstack/marketplace-sdk/1.4.1: - resolution: {integrity: sha512-gxklP8+m7Grb4lRudXXNG9BOAiSkTw7Ua8oC9IAAmCfa1BSDMhh7XNphSM5Jj4paH/+1ZQ/StExU7R4MfcIZ1w==} + /@contentstack/management/1.27.2_debug@4.4.3: + resolution: {integrity: sha512-lCFJtWrYimYb+D/imQkE//flkywPychLU6OF2mMwZkIdS5bihauoZK9gbzdagz+P1y4KEvToWJpsx5E25EX8nQ==} + engines: {node: '>=8.0.0'} + dependencies: + '@contentstack/utils': 1.6.3 + assert: 2.1.0 + axios: 1.13.2_debug@4.4.3 + buffer: 6.0.3 + form-data: 4.0.5 + husky: 9.1.7 + lodash: 4.17.21 + otplib: 12.0.1 + qs: 6.14.1 + stream-browserify: 3.0.0 + transitivePeerDependencies: + - debug + dev: false + + /@contentstack/marketplace-sdk/1.4.2: + resolution: {integrity: sha512-eFwSWif5RmHJqniYHNzkC1P0WUN90t1BPfEx8zR9pF0GKETELGVtIwf0tFJ9Ag7zPchQZ63qtcbAQ4WJYWN/+w==} + requiresBuild: true dependencies: axios: 1.13.2 transitivePeerDependencies: - debug - /@contentstack/marketplace-sdk/1.4.1_debug@4.4.3: - resolution: {integrity: sha512-gxklP8+m7Grb4lRudXXNG9BOAiSkTw7Ua8oC9IAAmCfa1BSDMhh7XNphSM5Jj4paH/+1ZQ/StExU7R4MfcIZ1w==} + /@contentstack/marketplace-sdk/1.4.2_debug@4.4.3: + resolution: {integrity: sha512-eFwSWif5RmHJqniYHNzkC1P0WUN90t1BPfEx8zR9pF0GKETELGVtIwf0tFJ9Ag7zPchQZ63qtcbAQ4WJYWN/+w==} + requiresBuild: true dependencies: axios: 1.13.2_debug@4.4.3 transitivePeerDependencies: @@ -2609,7 +2643,7 @@ packages: engines: {node: '>=18'} dependencies: '@types/estree': 1.0.8 - '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/types': 8.53.1 comment-parser: 1.4.1 esquery: 1.7.0 jsdoc-type-pratt-parser: 4.1.0 @@ -3875,6 +3909,13 @@ packages: wrap-ansi-cjs: /wrap-ansi/7.0.0 dev: true + /@isaacs/fs-minipass/4.0.1: + resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} + engines: {node: '>=18.0.0'} + dependencies: + minipass: 7.1.2 + dev: false + /@istanbuljs/load-nyc-config/1.1.0: resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} engines: {node: '>=8'} @@ -4363,7 +4404,7 @@ packages: config-chain: 1.1.13 dev: true - /@rollup/plugin-commonjs/28.0.9_rollup@4.55.1: + /@rollup/plugin-commonjs/28.0.9_rollup@4.55.3: resolution: {integrity: sha512-PIR4/OHZ79romx0BVVll/PkwWpJ7e5lsqFa3gFfcrFPWwLXLV39JVUzQV9RKjWerE7B845Hqjj9VYlQeieZ2dA==} engines: {node: '>=16.0.0 || 14 >= 14.17'} peerDependencies: @@ -4372,17 +4413,17 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.3.0_rollup@4.55.1 + '@rollup/pluginutils': 5.3.0_rollup@4.55.3 commondir: 1.0.1 estree-walker: 2.0.2 fdir: 6.5.0_picomatch@4.0.3 is-reference: 1.2.1 magic-string: 0.30.21 picomatch: 4.0.3 - rollup: 4.55.1 + rollup: 4.55.3 dev: false - /@rollup/plugin-json/6.1.0_rollup@4.55.1: + /@rollup/plugin-json/6.1.0_rollup@4.55.3: resolution: {integrity: sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -4391,11 +4432,11 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.3.0_rollup@4.55.1 - rollup: 4.55.1 + '@rollup/pluginutils': 5.3.0_rollup@4.55.3 + rollup: 4.55.3 dev: false - /@rollup/plugin-node-resolve/16.0.3_rollup@4.55.1: + /@rollup/plugin-node-resolve/16.0.3_rollup@4.55.3: resolution: {integrity: sha512-lUYM3UBGuM93CnMPG1YocWu7X802BrNF3jW2zny5gQyLQgRFJhV1Sq0Zi74+dh/6NBx1DxFC4b4GXg9wUCG5Qg==} engines: {node: '>=14.0.0'} peerDependencies: @@ -4404,15 +4445,15 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.3.0_rollup@4.55.1 + '@rollup/pluginutils': 5.3.0_rollup@4.55.3 '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-module: 1.0.0 resolve: 1.22.11 - rollup: 4.55.1 + rollup: 4.55.3 dev: false - /@rollup/plugin-typescript/12.3.0_5ruxaqqe36fu6wuhs7btsktcwq: + /@rollup/plugin-typescript/12.3.0_4rny3w3kvl665dbmrblgq4incy: resolution: {integrity: sha512-7DP0/p7y3t67+NabT9f8oTBFE6gGkto4SA6Np2oudYmZE/m1dt8RB0SjL1msMxFpLo631qjRCcBlAbq1ml/Big==} engines: {node: '>=14.0.0'} peerDependencies: @@ -4425,14 +4466,14 @@ packages: tslib: optional: true dependencies: - '@rollup/pluginutils': 5.3.0_rollup@4.55.1 + '@rollup/pluginutils': 5.3.0_rollup@4.55.3 resolve: 1.22.11 - rollup: 4.55.1 + rollup: 4.55.3 tslib: 2.8.1 typescript: 4.9.5 dev: false - /@rollup/pluginutils/5.3.0_rollup@4.55.1: + /@rollup/pluginutils/5.3.0_rollup@4.55.3: resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==} engines: {node: '>=14.0.0'} peerDependencies: @@ -4444,203 +4485,203 @@ packages: '@types/estree': 1.0.8 estree-walker: 2.0.2 picomatch: 4.0.3 - rollup: 4.55.1 + rollup: 4.55.3 dev: false - /@rollup/rollup-android-arm-eabi/4.55.1: - resolution: {integrity: sha512-9R0DM/ykwfGIlNu6+2U09ga0WXeZ9MRC2Ter8jnz8415VbuIykVuc6bhdrbORFZANDmTDvq26mJrEVTl8TdnDg==} + /@rollup/rollup-android-arm-eabi/4.55.3: + resolution: {integrity: sha512-qyX8+93kK/7R5BEXPC2PjUt0+fS/VO2BVHjEHyIEWiYn88rcRBHmdLgoJjktBltgAf+NY7RfCGB1SoyKS/p9kg==} cpu: [arm] os: [android] requiresBuild: true dev: false optional: true - /@rollup/rollup-android-arm64/4.55.1: - resolution: {integrity: sha512-eFZCb1YUqhTysgW3sj/55du5cG57S7UTNtdMjCW7LwVcj3dTTcowCsC8p7uBdzKsZYa8J7IDE8lhMI+HX1vQvg==} + /@rollup/rollup-android-arm64/4.55.3: + resolution: {integrity: sha512-6sHrL42bjt5dHQzJ12Q4vMKfN+kUnZ0atHHnv4V0Wd9JMTk7FDzSY35+7qbz3ypQYMBPANbpGK7JpnWNnhGt8g==} cpu: [arm64] os: [android] requiresBuild: true dev: false optional: true - /@rollup/rollup-darwin-arm64/4.55.1: - resolution: {integrity: sha512-p3grE2PHcQm2e8PSGZdzIhCKbMCw/xi9XvMPErPhwO17vxtvCN5FEA2mSLgmKlCjHGMQTP6phuQTYWUnKewwGg==} + /@rollup/rollup-darwin-arm64/4.55.3: + resolution: {integrity: sha512-1ht2SpGIjEl2igJ9AbNpPIKzb1B5goXOcmtD0RFxnwNuMxqkR6AUaaErZz+4o+FKmzxcSNBOLrzsICZVNYa1Rw==} cpu: [arm64] os: [darwin] requiresBuild: true dev: false optional: true - /@rollup/rollup-darwin-x64/4.55.1: - resolution: {integrity: sha512-rDUjG25C9qoTm+e02Esi+aqTKSBYwVTaoS1wxcN47/Luqef57Vgp96xNANwt5npq9GDxsH7kXxNkJVEsWEOEaQ==} + /@rollup/rollup-darwin-x64/4.55.3: + resolution: {integrity: sha512-FYZ4iVunXxtT+CZqQoPVwPhH7549e/Gy7PIRRtq4t5f/vt54pX6eG9ebttRH6QSH7r/zxAFA4EZGlQ0h0FvXiA==} cpu: [x64] os: [darwin] requiresBuild: true dev: false optional: true - /@rollup/rollup-freebsd-arm64/4.55.1: - resolution: {integrity: sha512-+JiU7Jbp5cdxekIgdte0jfcu5oqw4GCKr6i3PJTlXTCU5H5Fvtkpbs4XJHRmWNXF+hKmn4v7ogI5OQPaupJgOg==} + /@rollup/rollup-freebsd-arm64/4.55.3: + resolution: {integrity: sha512-M/mwDCJ4wLsIgyxv2Lj7Len+UMHd4zAXu4GQ2UaCdksStglWhP61U3uowkaYBQBhVoNpwx5Hputo8eSqM7K82Q==} cpu: [arm64] os: [freebsd] requiresBuild: true dev: false optional: true - /@rollup/rollup-freebsd-x64/4.55.1: - resolution: {integrity: sha512-V5xC1tOVWtLLmr3YUk2f6EJK4qksksOYiz/TCsFHu/R+woubcLWdC9nZQmwjOAbmExBIVKsm1/wKmEy4z4u4Bw==} + /@rollup/rollup-freebsd-x64/4.55.3: + resolution: {integrity: sha512-5jZT2c7jBCrMegKYTYTpni8mg8y3uY8gzeq2ndFOANwNuC/xJbVAoGKR9LhMDA0H3nIhvaqUoBEuJoICBudFrA==} cpu: [x64] os: [freebsd] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-arm-gnueabihf/4.55.1: - resolution: {integrity: sha512-Rn3n+FUk2J5VWx+ywrG/HGPTD9jXNbicRtTM11e/uorplArnXZYsVifnPPqNNP5BsO3roI4n8332ukpY/zN7rQ==} + /@rollup/rollup-linux-arm-gnueabihf/4.55.3: + resolution: {integrity: sha512-YeGUhkN1oA+iSPzzhEjVPS29YbViOr8s4lSsFaZKLHswgqP911xx25fPOyE9+khmN6W4VeM0aevbDp4kkEoHiA==} cpu: [arm] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-arm-musleabihf/4.55.1: - resolution: {integrity: sha512-grPNWydeKtc1aEdrJDWk4opD7nFtQbMmV7769hiAaYyUKCT1faPRm2av8CX1YJsZ4TLAZcg9gTR1KvEzoLjXkg==} + /@rollup/rollup-linux-arm-musleabihf/4.55.3: + resolution: {integrity: sha512-eo0iOIOvcAlWB3Z3eh8pVM8hZ0oVkK3AjEM9nSrkSug2l15qHzF3TOwT0747omI6+CJJvl7drwZepT+re6Fy/w==} cpu: [arm] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-arm64-gnu/4.55.1: - resolution: {integrity: sha512-a59mwd1k6x8tXKcUxSyISiquLwB5pX+fJW9TkWU46lCqD/GRDe9uDN31jrMmVP3feI3mhAdvcCClhV8V5MhJFQ==} + /@rollup/rollup-linux-arm64-gnu/4.55.3: + resolution: {integrity: sha512-DJay3ep76bKUDImmn//W5SvpjRN5LmK/ntWyeJs/dcnwiiHESd3N4uteK9FDLf0S0W8E6Y0sVRXpOCoQclQqNg==} cpu: [arm64] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-arm64-musl/4.55.1: - resolution: {integrity: sha512-puS1MEgWX5GsHSoiAsF0TYrpomdvkaXm0CofIMG5uVkP6IBV+ZO9xhC5YEN49nsgYo1DuuMquF9+7EDBVYu4uA==} + /@rollup/rollup-linux-arm64-musl/4.55.3: + resolution: {integrity: sha512-BKKWQkY2WgJ5MC/ayvIJTHjy0JUGb5efaHCUiG/39sSUvAYRBaO3+/EK0AZT1RF3pSj86O24GLLik9mAYu0IJg==} cpu: [arm64] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-loong64-gnu/4.55.1: - resolution: {integrity: sha512-r3Wv40in+lTsULSb6nnoudVbARdOwb2u5fpeoOAZjFLznp6tDU8kd+GTHmJoqZ9lt6/Sys33KdIHUaQihFcu7g==} + /@rollup/rollup-linux-loong64-gnu/4.55.3: + resolution: {integrity: sha512-Q9nVlWtKAG7ISW80OiZGxTr6rYtyDSkauHUtvkQI6TNOJjFvpj4gcH+KaJihqYInnAzEEUetPQubRwHef4exVg==} cpu: [loong64] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-loong64-musl/4.55.1: - resolution: {integrity: sha512-MR8c0+UxAlB22Fq4R+aQSPBayvYa3+9DrwG/i1TKQXFYEaoW3B5b/rkSRIypcZDdWjWnpcvxbNaAJDcSbJU3Lw==} + /@rollup/rollup-linux-loong64-musl/4.55.3: + resolution: {integrity: sha512-2H5LmhzrpC4fFRNwknzmmTvvyJPHwESoJgyReXeFoYYuIDfBhP29TEXOkCJE/KxHi27mj7wDUClNq78ue3QEBQ==} cpu: [loong64] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-ppc64-gnu/4.55.1: - resolution: {integrity: sha512-3KhoECe1BRlSYpMTeVrD4sh2Pw2xgt4jzNSZIIPLFEsnQn9gAnZagW9+VqDqAHgm1Xc77LzJOo2LdigS5qZ+gw==} + /@rollup/rollup-linux-ppc64-gnu/4.55.3: + resolution: {integrity: sha512-9S542V0ie9LCTznPYlvaeySwBeIEa7rDBgLHKZ5S9DBgcqdJYburabm8TqiqG6mrdTzfV5uttQRHcbKff9lWtA==} cpu: [ppc64] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-ppc64-musl/4.55.1: - resolution: {integrity: sha512-ziR1OuZx0vdYZZ30vueNZTg73alF59DicYrPViG0NEgDVN8/Jl87zkAPu4u6VjZST2llgEUjaiNl9JM6HH1Vdw==} + /@rollup/rollup-linux-ppc64-musl/4.55.3: + resolution: {integrity: sha512-ukxw+YH3XXpcezLgbJeasgxyTbdpnNAkrIlFGDl7t+pgCxZ89/6n1a+MxlY7CegU+nDgrgdqDelPRNQ/47zs0g==} cpu: [ppc64] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-riscv64-gnu/4.55.1: - resolution: {integrity: sha512-uW0Y12ih2XJRERZ4jAfKamTyIHVMPQnTZcQjme2HMVDAHY4amf5u414OqNYC+x+LzRdRcnIG1YodLrrtA8xsxw==} + /@rollup/rollup-linux-riscv64-gnu/4.55.3: + resolution: {integrity: sha512-Iauw9UsTTvlF++FhghFJjqYxyXdggXsOqGpFBylaRopVpcbfyIIsNvkf9oGwfgIcf57z3m8+/oSYTo6HutBFNw==} cpu: [riscv64] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-riscv64-musl/4.55.1: - resolution: {integrity: sha512-u9yZ0jUkOED1BFrqu3BwMQoixvGHGZ+JhJNkNKY/hyoEgOwlqKb62qu+7UjbPSHYjiVy8kKJHvXKv5coH4wDeg==} + /@rollup/rollup-linux-riscv64-musl/4.55.3: + resolution: {integrity: sha512-3OqKAHSEQXKdq9mQ4eajqUgNIK27VZPW3I26EP8miIzuKzCJ3aW3oEn2pzF+4/Hj/Moc0YDsOtBgT5bZ56/vcA==} cpu: [riscv64] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-s390x-gnu/4.55.1: - resolution: {integrity: sha512-/0PenBCmqM4ZUd0190j7J0UsQ/1nsi735iPRakO8iPciE7BQ495Y6msPzaOmvx0/pn+eJVVlZrNrSh4WSYLxNg==} + /@rollup/rollup-linux-s390x-gnu/4.55.3: + resolution: {integrity: sha512-0CM8dSVzVIaqMcXIFej8zZrSFLnGrAE8qlNbbHfTw1EEPnFTg1U1ekI0JdzjPyzSfUsHWtodilQQG/RA55berA==} cpu: [s390x] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-x64-gnu/4.55.1: - resolution: {integrity: sha512-a8G4wiQxQG2BAvo+gU6XrReRRqj+pLS2NGXKm8io19goR+K8lw269eTrPkSdDTALwMmJp4th2Uh0D8J9bEV1vg==} + /@rollup/rollup-linux-x64-gnu/4.55.3: + resolution: {integrity: sha512-+fgJE12FZMIgBaKIAGd45rxf+5ftcycANJRWk8Vz0NnMTM5rADPGuRFTYar+Mqs560xuART7XsX2lSACa1iOmQ==} cpu: [x64] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-linux-x64-musl/4.55.1: - resolution: {integrity: sha512-bD+zjpFrMpP/hqkfEcnjXWHMw5BIghGisOKPj+2NaNDuVT+8Ds4mPf3XcPHuat1tz89WRL+1wbcxKY3WSbiT7w==} + /@rollup/rollup-linux-x64-musl/4.55.3: + resolution: {integrity: sha512-tMD7NnbAolWPzQlJQJjVFh/fNH3K/KnA7K8gv2dJWCwwnaK6DFCYST1QXYWfu5V0cDwarWC8Sf/cfMHniNq21A==} cpu: [x64] os: [linux] requiresBuild: true dev: false optional: true - /@rollup/rollup-openbsd-x64/4.55.1: - resolution: {integrity: sha512-eLXw0dOiqE4QmvikfQ6yjgkg/xDM+MdU9YJuP4ySTibXU0oAvnEWXt7UDJmD4UkYialMfOGFPJnIHSe/kdzPxg==} + /@rollup/rollup-openbsd-x64/4.55.3: + resolution: {integrity: sha512-u5KsqxOxjEeIbn7bUK1MPM34jrnPwjeqgyin4/N6e/KzXKfpE9Mi0nCxcQjaM9lLmPcHmn/xx1yOjgTMtu1jWQ==} cpu: [x64] os: [openbsd] requiresBuild: true dev: false optional: true - /@rollup/rollup-openharmony-arm64/4.55.1: - resolution: {integrity: sha512-xzm44KgEP11te3S2HCSyYf5zIzWmx3n8HDCc7EE59+lTcswEWNpvMLfd9uJvVX8LCg9QWG67Xt75AuHn4vgsXw==} + /@rollup/rollup-openharmony-arm64/4.55.3: + resolution: {integrity: sha512-vo54aXwjpTtsAnb3ca7Yxs9t2INZg7QdXN/7yaoG7nPGbOBXYXQY41Km+S1Ov26vzOAzLcAjmMdjyEqS1JkVhw==} cpu: [arm64] os: [openharmony] requiresBuild: true dev: false optional: true - /@rollup/rollup-win32-arm64-msvc/4.55.1: - resolution: {integrity: sha512-yR6Bl3tMC/gBok5cz/Qi0xYnVbIxGx5Fcf/ca0eB6/6JwOY+SRUcJfI0OpeTpPls7f194as62thCt/2BjxYN8g==} + /@rollup/rollup-win32-arm64-msvc/4.55.3: + resolution: {integrity: sha512-HI+PIVZ+m+9AgpnY3pt6rinUdRYrGHvmVdsNQ4odNqQ/eRF78DVpMR7mOq7nW06QxpczibwBmeQzB68wJ+4W4A==} cpu: [arm64] os: [win32] requiresBuild: true dev: false optional: true - /@rollup/rollup-win32-ia32-msvc/4.55.1: - resolution: {integrity: sha512-3fZBidchE0eY0oFZBnekYCfg+5wAB0mbpCBuofh5mZuzIU/4jIVkbESmd2dOsFNS78b53CYv3OAtwqkZZmU5nA==} + /@rollup/rollup-win32-ia32-msvc/4.55.3: + resolution: {integrity: sha512-vRByotbdMo3Wdi+8oC2nVxtc3RkkFKrGaok+a62AT8lz/YBuQjaVYAS5Zcs3tPzW43Vsf9J0wehJbUY5xRSekA==} cpu: [ia32] os: [win32] requiresBuild: true dev: false optional: true - /@rollup/rollup-win32-x64-gnu/4.55.1: - resolution: {integrity: sha512-xGGY5pXj69IxKb4yv/POoocPy/qmEGhimy/FoTpTSVju3FYXUQQMFCaZZXJVidsmGxRioZAwpThl/4zX41gRKg==} + /@rollup/rollup-win32-x64-gnu/4.55.3: + resolution: {integrity: sha512-POZHq7UeuzMJljC5NjKi8vKMFN6/5EOqcX1yGntNLp7rUTpBAXQ1hW8kWPFxYLv07QMcNM75xqVLGPWQq6TKFA==} cpu: [x64] os: [win32] requiresBuild: true dev: false optional: true - /@rollup/rollup-win32-x64-msvc/4.55.1: - resolution: {integrity: sha512-SPEpaL6DX4rmcXtnhdrQYgzQ5W2uW3SCJch88lB2zImhJRhIIK44fkUrgIV/Q8yUNfw5oyZ5vkeQsZLhCb06lw==} + /@rollup/rollup-win32-x64-msvc/4.55.3: + resolution: {integrity: sha512-aPFONczE4fUFKNXszdvnd2GqKEYQdV5oEsIbKPujJmWlCI9zEsv1Otig8RKK+X9bed9gFUN6LAeN4ZcNuu4zjg==} cpu: [x64] os: [win32] requiresBuild: true @@ -4748,8 +4789,8 @@ packages: tslib: 2.8.1 dev: true - /@smithy/core/3.20.7: - resolution: {integrity: sha512-aO7jmh3CtrmPsIJxUwYIzI5WVlMK8BMCPQ4D4nTzqTqBhbzvxHNzBMGcEg13yg/z9R2Qsz49NUFl0F0lVbTVFw==} + /@smithy/core/3.21.0: + resolution: {integrity: sha512-bg2TfzgsERyETAxc/Ims/eJX8eAnIeTi4r4LHpMpfF/2NyO6RsWis0rjKcCPaGksljmOb23BZRiCeT/3NvwkXw==} engines: {node: '>=18.0.0'} dependencies: '@smithy/middleware-serde': 4.2.9 @@ -4900,11 +4941,11 @@ packages: tslib: 2.8.1 dev: true - /@smithy/middleware-endpoint/4.4.8: - resolution: {integrity: sha512-TV44qwB/T0OMMzjIuI+JeS0ort3bvlPJ8XIH0MSlGADraXpZqmyND27ueuAL3E14optleADWqtd7dUgc2w+qhQ==} + /@smithy/middleware-endpoint/4.4.10: + resolution: {integrity: sha512-kwWpNltpxrvPabnjEFvwSmA+66l6s2ReCvgVSzW/z92LU4T28fTdgZ18IdYRYOrisu2NMQ0jUndRScbO65A/zg==} engines: {node: '>=18.0.0'} dependencies: - '@smithy/core': 3.20.7 + '@smithy/core': 3.21.0 '@smithy/middleware-serde': 4.2.9 '@smithy/node-config-provider': 4.3.8 '@smithy/shared-ini-file-loader': 4.4.3 @@ -4914,14 +4955,14 @@ packages: tslib: 2.8.1 dev: true - /@smithy/middleware-retry/4.4.24: - resolution: {integrity: sha512-yiUY1UvnbUFfP5izoKLtfxDSTRv724YRRwyiC/5HYY6vdsVDcDOXKSXmkJl/Hovcxt5r+8tZEUAdrOaCJwrl9Q==} + /@smithy/middleware-retry/4.4.26: + resolution: {integrity: sha512-ozZMoTAr+B2aVYfLYfkssFvc8ZV3p/vLpVQ7/k277xxUOA9ykSPe5obL2j6yHfbdrM/SZV7qj0uk/hSqavHrLw==} engines: {node: '>=18.0.0'} dependencies: '@smithy/node-config-provider': 4.3.8 '@smithy/protocol-http': 5.3.8 '@smithy/service-error-classification': 4.2.8 - '@smithy/smithy-client': 4.10.9 + '@smithy/smithy-client': 4.10.11 '@smithy/types': 4.12.0 '@smithy/util-middleware': 4.2.8 '@smithy/util-retry': 4.2.8 @@ -5029,12 +5070,12 @@ packages: tslib: 2.8.1 dev: true - /@smithy/smithy-client/4.10.9: - resolution: {integrity: sha512-Je0EvGXVJ0Vrrr2lsubq43JGRIluJ/hX17aN/W/A0WfE+JpoMdI8kwk2t9F0zTX9232sJDGcoH4zZre6m6f/sg==} + /@smithy/smithy-client/4.10.11: + resolution: {integrity: sha512-6o804SCyHGMXAb5mFJ+iTy9kVKv7F91a9szN0J+9X6p8A0NrdpUxdaC57aye2ipQkP2C4IAqETEpGZ0Zj77Haw==} engines: {node: '>=18.0.0'} dependencies: - '@smithy/core': 3.20.7 - '@smithy/middleware-endpoint': 4.4.8 + '@smithy/core': 3.21.0 + '@smithy/middleware-endpoint': 4.4.10 '@smithy/middleware-stack': 4.2.8 '@smithy/protocol-http': 5.3.8 '@smithy/types': 4.12.0 @@ -5104,25 +5145,25 @@ packages: tslib: 2.8.1 dev: true - /@smithy/util-defaults-mode-browser/4.3.23: - resolution: {integrity: sha512-mMg+r/qDfjfF/0psMbV4zd7F/i+rpyp7Hjh0Wry7eY15UnzTEId+xmQTGDU8IdZtDfbGQxuWNfgBZKBj+WuYbA==} + /@smithy/util-defaults-mode-browser/4.3.25: + resolution: {integrity: sha512-8ugoNMtss2dJHsXnqsibGPqoaafvWJPACmYKxJ4E6QWaDrixsAemmiMMAVbvwYadjR0H9G2+AlzsInSzRi8PSw==} engines: {node: '>=18.0.0'} dependencies: '@smithy/property-provider': 4.2.8 - '@smithy/smithy-client': 4.10.9 + '@smithy/smithy-client': 4.10.11 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true - /@smithy/util-defaults-mode-node/4.2.26: - resolution: {integrity: sha512-EQqe/WkbCinah0h1lMWh9ICl0Ob4lyl20/10WTB35SC9vDQfD8zWsOT+x2FIOXKAoZQ8z/y0EFMoodbcqWJY/w==} + /@smithy/util-defaults-mode-node/4.2.28: + resolution: {integrity: sha512-mjUdcP8h3E0K/XvNMi9oBXRV3DMCzeRiYIieZ1LQ7jq5tu6GH/GTWym7a1xIIE0pKSoLcpGsaImuQhGPSIJzAA==} engines: {node: '>=18.0.0'} dependencies: '@smithy/config-resolver': 4.4.6 '@smithy/credential-provider-imds': 4.2.8 '@smithy/node-config-provider': 4.3.8 '@smithy/property-provider': 4.2.8 - '@smithy/smithy-client': 4.10.9 + '@smithy/smithy-client': 4.10.11 '@smithy/types': 4.12.0 tslib: 2.8.1 dev: true @@ -5225,7 +5266,7 @@ packages: peerDependencies: eslint: '>=8.40.0' dependencies: - '@typescript-eslint/utils': 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/utils': 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji eslint: 8.57.1 eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -5242,7 +5283,7 @@ packages: peerDependencies: eslint: '>=8.40.0' dependencies: - '@typescript-eslint/utils': 8.53.0_eslint@7.32.0 + '@typescript-eslint/utils': 8.53.1_eslint@7.32.0 eslint: 7.32.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -5259,7 +5300,7 @@ packages: peerDependencies: eslint: '>=8.40.0' dependencies: - '@typescript-eslint/utils': 8.53.0_eslint@8.57.1 + '@typescript-eslint/utils': 8.53.1_eslint@8.57.1 eslint: 8.57.1 eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -5276,7 +5317,7 @@ packages: peerDependencies: eslint: '>=8.40.0' dependencies: - '@typescript-eslint/utils': 8.53.0_k2rwabtyo525wwqr6566umnmhy + '@typescript-eslint/utils': 8.53.1_k2rwabtyo525wwqr6566umnmhy eslint: 8.57.1 eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -5294,10 +5335,10 @@ packages: eslint: '>=9.0.0' dependencies: '@eslint-community/eslint-utils': 4.9.1_eslint@7.32.0 - '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/types': 8.53.1 eslint: 7.32.0 eslint-visitor-keys: 5.0.0 - espree: 11.0.0 + espree: 11.1.0 estraverse: 5.3.0 picomatch: 4.0.3 dev: true @@ -5309,10 +5350,10 @@ packages: eslint: '>=9.0.0' dependencies: '@eslint-community/eslint-utils': 4.9.1_eslint@8.57.1 - '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/types': 8.53.1 eslint: 8.57.1 eslint-visitor-keys: 5.0.0 - espree: 11.0.0 + espree: 11.1.0 estraverse: 5.3.0 picomatch: 4.0.3 dev: true @@ -5532,7 +5573,7 @@ packages: /@types/mkdirp/1.0.2: resolution: {integrity: sha512-o0K1tSO0Dx5X6xlU5F1D6625FawhC3dU3iqr25lluNv/+/QIVH8RLNEiVokgIZo+mz+87w/3Mkg/VvQS+J51fQ==} dependencies: - '@types/node': 14.18.63 + '@types/node': 20.19.30 dev: true /@types/mocha/10.0.10: @@ -5765,43 +5806,42 @@ packages: - supports-color dev: true - /@typescript-eslint/eslint-plugin/8.53.0_dca5iuiroy2vtdg3rzjjbhb4hm: - resolution: {integrity: sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==} + /@typescript-eslint/eslint-plugin/8.53.1_2552pu7bmmaqmdrlq4uwpduy5y: + resolution: {integrity: sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.53.0 + '@typescript-eslint/parser': ^8.53.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/type-utils': 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji - '@typescript-eslint/utils': 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/parser': 8.53.1_eslint@8.57.1 + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/type-utils': 8.53.1_eslint@8.57.1 + '@typescript-eslint/utils': 8.53.1_eslint@8.57.1 + '@typescript-eslint/visitor-keys': 8.53.1 eslint: 8.57.1 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.4.0_typescript@4.9.5 - typescript: 4.9.5 + ts-api-utils: 2.4.0 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/eslint-plugin/8.53.0_t2s57xm67hp4nmvbkcu6rjdgci: - resolution: {integrity: sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==} + /@typescript-eslint/eslint-plugin/8.53.1_7f3ev5f4rgmdwp43lafel2uhym: + resolution: {integrity: sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.53.0 + '@typescript-eslint/parser': ^8.53.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.53.0_eslint@7.32.0 - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/type-utils': 8.53.0_eslint@7.32.0 - '@typescript-eslint/utils': 8.53.0_eslint@7.32.0 - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/parser': 8.53.1_eslint@7.32.0 + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/type-utils': 8.53.1_eslint@7.32.0 + '@typescript-eslint/utils': 8.53.1_eslint@7.32.0 + '@typescript-eslint/visitor-keys': 8.53.1 eslint: 7.32.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -5810,42 +5850,43 @@ packages: - supports-color dev: true - /@typescript-eslint/eslint-plugin/8.53.0_xxyirjqvxmya52bar37s3rf4zi: - resolution: {integrity: sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==} + /@typescript-eslint/eslint-plugin/8.53.1_pakcvjk7ygtc4zwskulha7s734: + resolution: {integrity: sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.53.0 + '@typescript-eslint/parser': ^8.53.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.53.0_eslint@8.57.1 - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/type-utils': 8.53.0_eslint@8.57.1 - '@typescript-eslint/utils': 8.53.0_eslint@8.57.1 - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/parser': 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/type-utils': 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/utils': 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/visitor-keys': 8.53.1 eslint: 8.57.1 ignore: 7.0.5 natural-compare: 1.4.0 - ts-api-utils: 2.4.0 + ts-api-utils: 2.4.0_typescript@4.9.5 + typescript: 4.9.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/eslint-plugin/8.53.0_zpj3n5bnn5jlhekjw5lfewwpsi: - resolution: {integrity: sha512-eEXsVvLPu8Z4PkFibtuFJLJOTAV/nPdgtSjkGoPpddpFk3/ym2oy97jynY6ic2m6+nc5M8SE1e9v/mHKsulcJg==} + /@typescript-eslint/eslint-plugin/8.53.1_pyvuimufhdaxzjwomxqp7i7ijm: + resolution: {integrity: sha512-cFYYFZ+oQFi6hUnBTbLRXfTJiaQtYE3t4O692agbBl+2Zy+eqSKWtPjhPXJu1G7j4RLjKgeJPDdq3EqOwmX5Ag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^8.53.0 + '@typescript-eslint/parser': ^8.53.1 eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.53.0_k2rwabtyo525wwqr6566umnmhy - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/type-utils': 8.53.0_k2rwabtyo525wwqr6566umnmhy - '@typescript-eslint/utils': 8.53.0_k2rwabtyo525wwqr6566umnmhy - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/parser': 8.53.1_k2rwabtyo525wwqr6566umnmhy + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/type-utils': 8.53.1_k2rwabtyo525wwqr6566umnmhy + '@typescript-eslint/utils': 8.53.1_k2rwabtyo525wwqr6566umnmhy + '@typescript-eslint/visitor-keys': 8.53.1 eslint: 8.57.1 ignore: 7.0.5 natural-compare: 1.4.0 @@ -5897,17 +5938,17 @@ packages: - supports-color dev: true - /@typescript-eslint/parser/8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji: - resolution: {integrity: sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==} + /@typescript-eslint/parser/8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji: + resolution: {integrity: sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0_typescript@4.9.5 - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1_typescript@4.9.5 + '@typescript-eslint/visitor-keys': 8.53.1 debug: 4.4.3 eslint: 8.57.1 typescript: 4.9.5 @@ -5915,51 +5956,51 @@ packages: - supports-color dev: true - /@typescript-eslint/parser/8.53.0_eslint@7.32.0: - resolution: {integrity: sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==} + /@typescript-eslint/parser/8.53.1_eslint@7.32.0: + resolution: {integrity: sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0 - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1 + '@typescript-eslint/visitor-keys': 8.53.1 debug: 4.4.3 eslint: 7.32.0 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser/8.53.0_eslint@8.57.1: - resolution: {integrity: sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==} + /@typescript-eslint/parser/8.53.1_eslint@8.57.1: + resolution: {integrity: sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0 - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1 + '@typescript-eslint/visitor-keys': 8.53.1 debug: 4.4.3 eslint: 8.57.1 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/parser/8.53.0_k2rwabtyo525wwqr6566umnmhy: - resolution: {integrity: sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==} + /@typescript-eslint/parser/8.53.1_k2rwabtyo525wwqr6566umnmhy: + resolution: {integrity: sha512-nm3cvFN9SqZGXjmw5bZ6cGmvJSyJPn0wU9gHAZZHDnZl2wF9PhHv78Xf06E0MaNk4zLVHL8hb2/c32XvyJOLQg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0_typescript@5.9.3 - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1_typescript@5.9.3 + '@typescript-eslint/visitor-keys': 8.53.1 debug: 4.4.3 eslint: 8.57.1 typescript: 5.9.3 @@ -5967,41 +6008,41 @@ packages: - supports-color dev: true - /@typescript-eslint/project-service/8.53.0: - resolution: {integrity: sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==} + /@typescript-eslint/project-service/8.53.1: + resolution: {integrity: sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/tsconfig-utils': 8.53.0 - '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/tsconfig-utils': 8.53.1 + '@typescript-eslint/types': 8.53.1 debug: 4.4.3 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/project-service/8.53.0_typescript@4.9.5: - resolution: {integrity: sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==} + /@typescript-eslint/project-service/8.53.1_typescript@4.9.5: + resolution: {integrity: sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/tsconfig-utils': 8.53.0_typescript@4.9.5 - '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/tsconfig-utils': 8.53.1_typescript@4.9.5 + '@typescript-eslint/types': 8.53.1 debug: 4.4.3 typescript: 4.9.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/project-service/8.53.0_typescript@5.9.3: - resolution: {integrity: sha512-Bl6Gdr7NqkqIP5yP9z1JU///Nmes4Eose6L1HwpuVHwScgDPPuEWbUVhvlZmb8hy0vX9syLk5EGNL700WcBlbg==} + /@typescript-eslint/project-service/8.53.1_typescript@5.9.3: + resolution: {integrity: sha512-WYC4FB5Ra0xidsmlPb+1SsnaSKPmS3gsjIARwbEkHkoWloQmuzcfypljaJcR78uyLA1h8sHdWWPHSLDI+MtNog==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/tsconfig-utils': 8.53.0_typescript@5.9.3 - '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/tsconfig-utils': 8.53.1_typescript@5.9.3 + '@typescript-eslint/types': 8.53.1 debug: 4.4.3 typescript: 5.9.3 transitivePeerDependencies: @@ -6032,23 +6073,23 @@ packages: '@typescript-eslint/visitor-keys': 7.18.0 dev: true - /@typescript-eslint/scope-manager/8.53.0: - resolution: {integrity: sha512-kWNj3l01eOGSdVBnfAF2K1BTh06WS0Yet6JUgb9Cmkqaz3Jlu0fdVUjj9UI8gPidBWSMqDIglmEXifSgDT/D0g==} + /@typescript-eslint/scope-manager/8.53.1: + resolution: {integrity: sha512-Lu23yw1uJMFY8cUeq7JlrizAgeQvWugNQzJp8C3x8Eo5Jw5Q2ykMdiiTB9vBVOOUBysMzmRRmUfwFrZuI2C4SQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/visitor-keys': 8.53.1 dev: true - /@typescript-eslint/tsconfig-utils/8.53.0: - resolution: {integrity: sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==} + /@typescript-eslint/tsconfig-utils/8.53.1: + resolution: {integrity: sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' dev: true - /@typescript-eslint/tsconfig-utils/8.53.0_typescript@4.9.5: - resolution: {integrity: sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==} + /@typescript-eslint/tsconfig-utils/8.53.1_typescript@4.9.5: + resolution: {integrity: sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' @@ -6056,8 +6097,8 @@ packages: typescript: 4.9.5 dev: true - /@typescript-eslint/tsconfig-utils/8.53.0_typescript@5.9.3: - resolution: {integrity: sha512-K6Sc0R5GIG6dNoPdOooQ+KtvT5KCKAvTcY8h2rIuul19vxH5OTQk7ArKkd4yTzkw66WnNY0kPPzzcmWA+XRmiA==} + /@typescript-eslint/tsconfig-utils/8.53.1_typescript@5.9.3: + resolution: {integrity: sha512-qfvLXS6F6b1y43pnf0pPbXJ+YoXIC7HKg0UGZ27uMIemKMKA6XH2DTxsEDdpdN29D+vHV07x/pnlPNVLhdhWiA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' @@ -6125,16 +6166,16 @@ packages: - supports-color dev: true - /@typescript-eslint/type-utils/8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji: - resolution: {integrity: sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==} + /@typescript-eslint/type-utils/8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji: + resolution: {integrity: sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0_typescript@4.9.5 - '@typescript-eslint/utils': 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1_typescript@4.9.5 + '@typescript-eslint/utils': 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji debug: 4.4.3 eslint: 8.57.1 ts-api-utils: 2.4.0_typescript@4.9.5 @@ -6143,16 +6184,16 @@ packages: - supports-color dev: true - /@typescript-eslint/type-utils/8.53.0_eslint@7.32.0: - resolution: {integrity: sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==} + /@typescript-eslint/type-utils/8.53.1_eslint@7.32.0: + resolution: {integrity: sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0 - '@typescript-eslint/utils': 8.53.0_eslint@7.32.0 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1 + '@typescript-eslint/utils': 8.53.1_eslint@7.32.0 debug: 4.4.3 eslint: 7.32.0 ts-api-utils: 2.4.0 @@ -6160,16 +6201,16 @@ packages: - supports-color dev: true - /@typescript-eslint/type-utils/8.53.0_eslint@8.57.1: - resolution: {integrity: sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==} + /@typescript-eslint/type-utils/8.53.1_eslint@8.57.1: + resolution: {integrity: sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0 - '@typescript-eslint/utils': 8.53.0_eslint@8.57.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1 + '@typescript-eslint/utils': 8.53.1_eslint@8.57.1 debug: 4.4.3 eslint: 8.57.1 ts-api-utils: 2.4.0 @@ -6177,16 +6218,16 @@ packages: - supports-color dev: true - /@typescript-eslint/type-utils/8.53.0_k2rwabtyo525wwqr6566umnmhy: - resolution: {integrity: sha512-BBAUhlx7g4SmcLhn8cnbxoxtmS7hcq39xKCgiutL3oNx1TaIp+cny51s8ewnKMpVUKQUGb41RAUWZ9kxYdovuw==} + /@typescript-eslint/type-utils/8.53.1_k2rwabtyo525wwqr6566umnmhy: + resolution: {integrity: sha512-MOrdtNvyhy0rHyv0ENzub1d4wQYKb2NmIqG7qEqPWFW7Mpy2jzFC3pQ2yKDvirZB7jypm5uGjF2Qqs6OIqu47w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0_typescript@5.9.3 - '@typescript-eslint/utils': 8.53.0_k2rwabtyo525wwqr6566umnmhy + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1_typescript@5.9.3 + '@typescript-eslint/utils': 8.53.1_k2rwabtyo525wwqr6566umnmhy debug: 4.4.3 eslint: 8.57.1 ts-api-utils: 2.4.0_typescript@5.9.3 @@ -6210,8 +6251,8 @@ packages: engines: {node: ^18.18.0 || >=20.0.0} dev: true - /@typescript-eslint/types/8.53.0: - resolution: {integrity: sha512-Bmh9KX31Vlxa13+PqPvt4RzKRN1XORYSLlAE+sO1i28NkisGbTtSLFVB3l7PWdHtR3E0mVMuC7JilWJ99m2HxQ==} + /@typescript-eslint/types/8.53.1: + resolution: {integrity: sha512-jr/swrr2aRmUAUjW5/zQHbMaui//vQlsZcJKijZf3M26bnmLj8LyZUpj8/Rd6uzaek06OWsqdofN/Thenm5O8A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: true @@ -6324,16 +6365,16 @@ packages: - supports-color dev: true - /@typescript-eslint/typescript-estree/8.53.0: - resolution: {integrity: sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==} + /@typescript-eslint/typescript-estree/8.53.1: + resolution: {integrity: sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/project-service': 8.53.0 - '@typescript-eslint/tsconfig-utils': 8.53.0 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/project-service': 8.53.1 + '@typescript-eslint/tsconfig-utils': 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/visitor-keys': 8.53.1 debug: 4.4.3 minimatch: 9.0.5 semver: 7.7.3 @@ -6343,16 +6384,16 @@ packages: - supports-color dev: true - /@typescript-eslint/typescript-estree/8.53.0_typescript@4.9.5: - resolution: {integrity: sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==} + /@typescript-eslint/typescript-estree/8.53.1_typescript@4.9.5: + resolution: {integrity: sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/project-service': 8.53.0_typescript@4.9.5 - '@typescript-eslint/tsconfig-utils': 8.53.0_typescript@4.9.5 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/project-service': 8.53.1_typescript@4.9.5 + '@typescript-eslint/tsconfig-utils': 8.53.1_typescript@4.9.5 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/visitor-keys': 8.53.1 debug: 4.4.3 minimatch: 9.0.5 semver: 7.7.3 @@ -6363,16 +6404,16 @@ packages: - supports-color dev: true - /@typescript-eslint/typescript-estree/8.53.0_typescript@5.9.3: - resolution: {integrity: sha512-pw0c0Gdo7Z4xOG987u3nJ8akL9093yEEKv8QTJ+Bhkghj1xyj8cgPaavlr9rq8h7+s6plUJ4QJYw2gCZodqmGw==} + /@typescript-eslint/typescript-estree/8.53.1_typescript@5.9.3: + resolution: {integrity: sha512-RGlVipGhQAG4GxV1s34O91cxQ/vWiHJTDHbXRr0li2q/BGg3RR/7NM8QDWgkEgrwQYCvmJV9ichIwyoKCQ+DTg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/project-service': 8.53.0_typescript@5.9.3 - '@typescript-eslint/tsconfig-utils': 8.53.0_typescript@5.9.3 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/visitor-keys': 8.53.0 + '@typescript-eslint/project-service': 8.53.1_typescript@5.9.3 + '@typescript-eslint/tsconfig-utils': 8.53.1_typescript@5.9.3 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/visitor-keys': 8.53.1 debug: 4.4.3 minimatch: 9.0.5 semver: 7.7.3 @@ -6473,66 +6514,66 @@ packages: - typescript dev: true - /@typescript-eslint/utils/8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji: - resolution: {integrity: sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==} + /@typescript-eslint/utils/8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji: + resolution: {integrity: sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: '@eslint-community/eslint-utils': 4.9.1_eslint@8.57.1 - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0_typescript@4.9.5 + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1_typescript@4.9.5 eslint: 8.57.1 typescript: 4.9.5 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils/8.53.0_eslint@7.32.0: - resolution: {integrity: sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==} + /@typescript-eslint/utils/8.53.1_eslint@7.32.0: + resolution: {integrity: sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: '@eslint-community/eslint-utils': 4.9.1_eslint@7.32.0 - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0 + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1 eslint: 7.32.0 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils/8.53.0_eslint@8.57.1: - resolution: {integrity: sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==} + /@typescript-eslint/utils/8.53.1_eslint@8.57.1: + resolution: {integrity: sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: '@eslint-community/eslint-utils': 4.9.1_eslint@8.57.1 - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0 + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1 eslint: 8.57.1 transitivePeerDependencies: - supports-color dev: true - /@typescript-eslint/utils/8.53.0_k2rwabtyo525wwqr6566umnmhy: - resolution: {integrity: sha512-XDY4mXTez3Z1iRDI5mbRhH4DFSt46oaIFsLg+Zn97+sYrXACziXSQcSelMybnVZ5pa1P6xYkPr5cMJyunM1ZDA==} + /@typescript-eslint/utils/8.53.1_k2rwabtyo525wwqr6566umnmhy: + resolution: {integrity: sha512-c4bMvGVWW4hv6JmDUEG7fSYlWOl3II2I4ylt0NM+seinYQlZMQIaKaXIIVJWt9Ofh6whrpM+EdDQXKXjNovvrg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: '@eslint-community/eslint-utils': 4.9.1_eslint@8.57.1 - '@typescript-eslint/scope-manager': 8.53.0 - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/typescript-estree': 8.53.0_typescript@5.9.3 + '@typescript-eslint/scope-manager': 8.53.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/typescript-estree': 8.53.1_typescript@5.9.3 eslint: 8.57.1 typescript: 5.9.3 transitivePeerDependencies: @@ -6563,11 +6604,11 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /@typescript-eslint/visitor-keys/8.53.0: - resolution: {integrity: sha512-LZ2NqIHFhvFwxG0qZeLL9DvdNAHPGCY5dIRwBhyYeU+LfLhcStE1ImjsuTG/WaVh3XysGaeLW8Rqq7cGkPCFvw==} + /@typescript-eslint/visitor-keys/8.53.1: + resolution: {integrity: sha512-oy+wV7xDKFPRyNggmXuZQSBzvoLnpmJs+GhzRhPjrxl2b/jIlyjVokzm47CZCDUdXKr2zd7ZLodPfOBpOPyPlg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - '@typescript-eslint/types': 8.53.0 + '@typescript-eslint/types': 8.53.1 eslint-visitor-keys: 4.2.1 dev: true @@ -7243,8 +7284,8 @@ packages: /base64-js/1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - /baseline-browser-mapping/2.9.15: - resolution: {integrity: sha512-kX8h7K2srmDyYnXRIppo4AH/wYgzWVCs+eKr3RusRSQ5PvRYoEFmR/I0PbdTjKFAoKqp5+kbxnNTFO9jOfSVJg==} + /baseline-browser-mapping/2.9.16: + resolution: {integrity: sha512-KeUZdBuxngy825i8xvzaK1Ncnkx0tBmb3k8DkEuqjKRkmtvNTjey2ZsNeh8Dw4lfKvbCOu9oeNx2TKm2vHqcRw==} hasBin: true dev: true @@ -7331,7 +7372,7 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - baseline-browser-mapping: 2.9.15 + baseline-browser-mapping: 2.9.16 caniuse-lite: 1.0.30001765 electron-to-chromium: 1.5.267 node-releases: 2.0.27 @@ -7585,9 +7626,9 @@ packages: fsevents: 2.3.3 dev: true - /chownr/2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} + /chownr/3.0.0: + resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} + engines: {node: '>=18'} dev: false /ci-info/3.9.0: @@ -8198,13 +8239,13 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dev: true - /diff/4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + /diff/4.0.4: + resolution: {integrity: sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==} engines: {node: '>=0.3.1'} dev: true - /diff/5.2.0: - resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + /diff/5.2.2: + resolution: {integrity: sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==} engines: {node: '>=0.3.1'} dev: true @@ -8627,19 +8668,19 @@ packages: '@eslint/eslintrc': 3.3.3 '@eslint/js': 9.39.2 '@stylistic/eslint-plugin': 3.1.0_avq3eyf5kaj6ssrwo7fvkrwnji - '@typescript-eslint/eslint-plugin': 8.53.0_dca5iuiroy2vtdg3rzjjbhb4hm - '@typescript-eslint/parser': 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/eslint-plugin': 8.53.1_pakcvjk7ygtc4zwskulha7s734 + '@typescript-eslint/parser': 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji eslint-config-oclif: 5.2.2_eslint@8.57.1 eslint-config-xo: 0.49.0_eslint@8.57.1 eslint-config-xo-space: 0.35.0_eslint@8.57.1 eslint-import-resolver-typescript: 3.10.1_2exwcduccderqiu2u7qw4rc7d4 - eslint-plugin-import: 2.32.0_aksosxtone4o5zz7qyqktlzmn4 + eslint-plugin-import: 2.32.0_bwxiopfwkgreu7lomrnbat6ddq eslint-plugin-jsdoc: 50.8.0_eslint@8.57.1 eslint-plugin-mocha: 10.5.0_eslint@8.57.1 eslint-plugin-n: 17.23.2_avq3eyf5kaj6ssrwo7fvkrwnji eslint-plugin-perfectionist: 4.15.1_avq3eyf5kaj6ssrwo7fvkrwnji eslint-plugin-unicorn: 56.0.1_eslint@8.57.1 - typescript-eslint: 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji + typescript-eslint: 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji transitivePeerDependencies: - eslint - eslint-import-resolver-webpack @@ -8656,19 +8697,19 @@ packages: '@eslint/eslintrc': 3.3.3 '@eslint/js': 9.39.2 '@stylistic/eslint-plugin': 3.1.0_eslint@7.32.0 - '@typescript-eslint/eslint-plugin': 8.53.0_t2s57xm67hp4nmvbkcu6rjdgci - '@typescript-eslint/parser': 8.53.0_eslint@7.32.0 + '@typescript-eslint/eslint-plugin': 8.53.1_7f3ev5f4rgmdwp43lafel2uhym + '@typescript-eslint/parser': 8.53.1_eslint@7.32.0 eslint-config-oclif: 5.2.2_eslint@7.32.0 eslint-config-xo: 0.49.0_eslint@7.32.0 eslint-config-xo-space: 0.35.0_eslint@7.32.0 eslint-import-resolver-typescript: 3.10.1_euuv2s2m4azrqak6tzap5kwzai - eslint-plugin-import: 2.32.0_v6kaevju6un6uz2ubdc56kf7by + eslint-plugin-import: 2.32.0_6icihbrq4zzyh6aatylqrjvwgq eslint-plugin-jsdoc: 50.8.0_eslint@7.32.0 eslint-plugin-mocha: 10.5.0_eslint@7.32.0 eslint-plugin-n: 17.23.2_eslint@7.32.0 eslint-plugin-perfectionist: 4.15.1_eslint@7.32.0 eslint-plugin-unicorn: 56.0.1_eslint@7.32.0 - typescript-eslint: 8.53.0_eslint@7.32.0 + typescript-eslint: 8.53.1_eslint@7.32.0 transitivePeerDependencies: - eslint - eslint-import-resolver-webpack @@ -8685,19 +8726,19 @@ packages: '@eslint/eslintrc': 3.3.3 '@eslint/js': 9.39.2 '@stylistic/eslint-plugin': 3.1.0_eslint@8.57.1 - '@typescript-eslint/eslint-plugin': 8.53.0_xxyirjqvxmya52bar37s3rf4zi - '@typescript-eslint/parser': 8.53.0_eslint@8.57.1 + '@typescript-eslint/eslint-plugin': 8.53.1_2552pu7bmmaqmdrlq4uwpduy5y + '@typescript-eslint/parser': 8.53.1_eslint@8.57.1 eslint-config-oclif: 5.2.2_eslint@8.57.1 eslint-config-xo: 0.49.0_eslint@8.57.1 eslint-config-xo-space: 0.35.0_eslint@8.57.1 eslint-import-resolver-typescript: 3.10.1_2exwcduccderqiu2u7qw4rc7d4 - eslint-plugin-import: 2.32.0_aksosxtone4o5zz7qyqktlzmn4 + eslint-plugin-import: 2.32.0_bwxiopfwkgreu7lomrnbat6ddq eslint-plugin-jsdoc: 50.8.0_eslint@8.57.1 eslint-plugin-mocha: 10.5.0_eslint@8.57.1 eslint-plugin-n: 17.23.2_eslint@8.57.1 eslint-plugin-perfectionist: 4.15.1_eslint@8.57.1 eslint-plugin-unicorn: 56.0.1_eslint@8.57.1 - typescript-eslint: 8.53.0_eslint@8.57.1 + typescript-eslint: 8.53.1_eslint@8.57.1 transitivePeerDependencies: - eslint - eslint-import-resolver-webpack @@ -8714,19 +8755,19 @@ packages: '@eslint/eslintrc': 3.3.3 '@eslint/js': 9.39.2 '@stylistic/eslint-plugin': 3.1.0_k2rwabtyo525wwqr6566umnmhy - '@typescript-eslint/eslint-plugin': 8.53.0_zpj3n5bnn5jlhekjw5lfewwpsi - '@typescript-eslint/parser': 8.53.0_k2rwabtyo525wwqr6566umnmhy + '@typescript-eslint/eslint-plugin': 8.53.1_pyvuimufhdaxzjwomxqp7i7ijm + '@typescript-eslint/parser': 8.53.1_k2rwabtyo525wwqr6566umnmhy eslint-config-oclif: 5.2.2_eslint@8.57.1 eslint-config-xo: 0.49.0_eslint@8.57.1 eslint-config-xo-space: 0.35.0_eslint@8.57.1 eslint-import-resolver-typescript: 3.10.1_2exwcduccderqiu2u7qw4rc7d4 - eslint-plugin-import: 2.32.0_aksosxtone4o5zz7qyqktlzmn4 + eslint-plugin-import: 2.32.0_bwxiopfwkgreu7lomrnbat6ddq eslint-plugin-jsdoc: 50.8.0_eslint@8.57.1 eslint-plugin-mocha: 10.5.0_eslint@8.57.1 eslint-plugin-n: 17.23.2_k2rwabtyo525wwqr6566umnmhy eslint-plugin-perfectionist: 4.15.1_k2rwabtyo525wwqr6566umnmhy eslint-plugin-unicorn: 56.0.1_eslint@8.57.1 - typescript-eslint: 8.53.0_k2rwabtyo525wwqr6566umnmhy + typescript-eslint: 8.53.1_k2rwabtyo525wwqr6566umnmhy transitivePeerDependencies: - eslint - eslint-import-resolver-webpack @@ -8829,7 +8870,7 @@ packages: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 eslint: 8.57.1 - eslint-plugin-import: 2.32.0_aksosxtone4o5zz7qyqktlzmn4 + eslint-plugin-import: 2.32.0_bwxiopfwkgreu7lomrnbat6ddq get-tsconfig: 4.13.0 is-bun-module: 2.0.0 stable-hash: 0.0.5 @@ -8855,7 +8896,7 @@ packages: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.3 eslint: 7.32.0 - eslint-plugin-import: 2.32.0_v6kaevju6un6uz2ubdc56kf7by + eslint-plugin-import: 2.32.0_6icihbrq4zzyh6aatylqrjvwgq get-tsconfig: 4.13.0 is-bun-module: 2.0.0 stable-hash: 0.0.5 @@ -8865,7 +8906,7 @@ packages: - supports-color dev: true - /eslint-module-utils/2.12.1_jynnuuyasbbimpxpcgtebyfyda: + /eslint-module-utils/2.12.1_p6iyeyvinjevldd7q4c5gl6b6e: resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} engines: {node: '>=4'} peerDependencies: @@ -8886,7 +8927,7 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/parser': 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji debug: 3.2.7 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 @@ -8895,7 +8936,7 @@ packages: - supports-color dev: true - /eslint-module-utils/2.12.1_swrhntwfibhg62qifem35een4m: + /eslint-module-utils/2.12.1_yb2aych2lrsetdffcibe7ggstq: resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} engines: {node: '>=4'} peerDependencies: @@ -8916,16 +8957,16 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 8.53.0_eslint@7.32.0 + '@typescript-eslint/parser': 6.21.0_avq3eyf5kaj6ssrwo7fvkrwnji debug: 3.2.7 - eslint: 7.32.0 + eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1_euuv2s2m4azrqak6tzap5kwzai + eslint-import-resolver-typescript: 3.10.1_2exwcduccderqiu2u7qw4rc7d4 transitivePeerDependencies: - supports-color dev: true - /eslint-module-utils/2.12.1_yb2aych2lrsetdffcibe7ggstq: + /eslint-module-utils/2.12.1_zvqgrm2bcvv543jqlnq6q5dv5y: resolution: {integrity: sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==} engines: {node: '>=4'} peerDependencies: @@ -8946,11 +8987,11 @@ packages: eslint-import-resolver-webpack: optional: true dependencies: - '@typescript-eslint/parser': 6.21.0_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/parser': 8.53.1_eslint@7.32.0 debug: 3.2.7 - eslint: 8.57.1 + eslint: 7.32.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1_2exwcduccderqiu2u7qw4rc7d4 + eslint-import-resolver-typescript: 3.10.1_euuv2s2m4azrqak6tzap5kwzai transitivePeerDependencies: - supports-color dev: true @@ -9001,7 +9042,7 @@ packages: regexpp: 3.2.0 dev: true - /eslint-plugin-import/2.32.0_aksosxtone4o5zz7qyqktlzmn4: + /eslint-plugin-import/2.32.0_6icihbrq4zzyh6aatylqrjvwgq: resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} engines: {node: '>=4'} peerDependencies: @@ -9012,16 +9053,16 @@ packages: optional: true dependencies: '@rtsao/scc': 1.1.0 - '@typescript-eslint/parser': 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/parser': 8.53.1_eslint@7.32.0 array-includes: 3.1.9 array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 8.57.1 + eslint: 7.32.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1_jynnuuyasbbimpxpcgtebyfyda + eslint-module-utils: 2.12.1_zvqgrm2bcvv543jqlnq6q5dv5y hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -9075,7 +9116,7 @@ packages: - supports-color dev: true - /eslint-plugin-import/2.32.0_v6kaevju6un6uz2ubdc56kf7by: + /eslint-plugin-import/2.32.0_bwxiopfwkgreu7lomrnbat6ddq: resolution: {integrity: sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==} engines: {node: '>=4'} peerDependencies: @@ -9086,16 +9127,16 @@ packages: optional: true dependencies: '@rtsao/scc': 1.1.0 - '@typescript-eslint/parser': 8.53.0_eslint@7.32.0 + '@typescript-eslint/parser': 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji array-includes: 3.1.9 array.prototype.findlastindex: 1.2.6 array.prototype.flat: 1.3.3 array.prototype.flatmap: 1.3.3 debug: 3.2.7 doctrine: 2.1.0 - eslint: 7.32.0 + eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1_swrhntwfibhg62qifem35een4m + eslint-module-utils: 2.12.1_p6iyeyvinjevldd7q4c5gl6b6e hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -9352,8 +9393,8 @@ packages: peerDependencies: eslint: '>=8.45.0' dependencies: - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/utils': 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/utils': 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji eslint: 8.57.1 natural-orderby: 5.0.0 transitivePeerDependencies: @@ -9367,8 +9408,8 @@ packages: peerDependencies: eslint: '>=8.45.0' dependencies: - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/utils': 8.53.0_eslint@7.32.0 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/utils': 8.53.1_eslint@7.32.0 eslint: 7.32.0 natural-orderby: 5.0.0 transitivePeerDependencies: @@ -9382,8 +9423,8 @@ packages: peerDependencies: eslint: '>=8.45.0' dependencies: - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/utils': 8.53.0_eslint@8.57.1 + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/utils': 8.53.1_eslint@8.57.1 eslint: 8.57.1 natural-orderby: 5.0.0 transitivePeerDependencies: @@ -9397,8 +9438,8 @@ packages: peerDependencies: eslint: '>=8.45.0' dependencies: - '@typescript-eslint/types': 8.53.0 - '@typescript-eslint/utils': 8.53.0_k2rwabtyo525wwqr6566umnmhy + '@typescript-eslint/types': 8.53.1 + '@typescript-eslint/utils': 8.53.1_k2rwabtyo525wwqr6566umnmhy eslint: 8.57.1 natural-orderby: 5.0.0 transitivePeerDependencies: @@ -9735,8 +9776,8 @@ packages: eslint-visitor-keys: 4.2.1 dev: true - /espree/11.0.0: - resolution: {integrity: sha512-+gMeWRrIh/NsG+3NaLeWHuyeyk70p2tbvZIWBYcqQ4/7Xvars6GYTZNhF1sIeLcc6Wb11He5ffz3hsHyXFrw5A==} + /espree/11.1.0: + resolution: {integrity: sha512-WFWYhO1fV4iYkqOOvq8FbqIhr2pYfoDY0kCotMkDeNtGpiGGkZ1iov2u8ydjtgM8yF8rzK7oaTbw2NAzbAbehw==} engines: {node: ^20.19.0 || ^22.13.0 || >=24} dependencies: acorn: 8.15.0 @@ -10254,13 +10295,6 @@ packages: universalify: 0.1.2 dev: true - /fs-minipass/2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - dev: false - /fs-then-native/2.0.0: resolution: {integrity: sha512-X712jAOaWXkemQCAmWeg5rOT2i+KOpWz1Z/txk/cW0qlOu2oQ9H61vc5w3X/iyuUEfq/OyaFJ78/cZAQD1/bgA==} engines: {node: '>=4.0.0'} @@ -12463,33 +12497,20 @@ packages: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: true - /minipass/3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - dev: false - /minipass/4.2.8: resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} engines: {node: '>=8'} dev: true - /minipass/5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - dev: false - /minipass/7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} - /minizlib/2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} + /minizlib/3.1.0: + resolution: {integrity: sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==} + engines: {node: '>= 18'} dependencies: - minipass: 3.3.6 - yallist: 4.0.0 + minipass: 7.1.2 dev: false /mixme/0.5.10: @@ -12520,7 +12541,7 @@ packages: browser-stdout: 1.3.1 chokidar: 3.6.0 debug: 4.4.3_supports-color@8.1.1 - diff: 5.2.0 + diff: 5.2.2 escape-string-regexp: 4.0.0 find-up: 5.0.0 glob: 8.1.0 @@ -12917,8 +12938,8 @@ packages: engines: {node: '>=18.0.0'} hasBin: true dependencies: - '@aws-sdk/client-cloudfront': 3.971.0 - '@aws-sdk/client-s3': 3.971.0 + '@aws-sdk/client-cloudfront': 3.972.0 + '@aws-sdk/client-s3': 3.972.0 '@inquirer/confirm': 3.2.0 '@inquirer/input': 2.3.0 '@inquirer/select': 2.5.0 @@ -12952,8 +12973,8 @@ packages: engines: {node: '>=18.0.0'} hasBin: true dependencies: - '@aws-sdk/client-cloudfront': 3.971.0 - '@aws-sdk/client-s3': 3.971.0 + '@aws-sdk/client-cloudfront': 3.972.0 + '@aws-sdk/client-s3': 3.972.0 '@inquirer/confirm': 3.2.0 '@inquirer/input': 2.3.0 '@inquirer/select': 2.5.0 @@ -12987,8 +13008,8 @@ packages: engines: {node: '>=18.0.0'} hasBin: true dependencies: - '@aws-sdk/client-cloudfront': 3.971.0 - '@aws-sdk/client-s3': 3.971.0 + '@aws-sdk/client-cloudfront': 3.972.0 + '@aws-sdk/client-s3': 3.972.0 '@inquirer/confirm': 3.2.0 '@inquirer/input': 2.3.0 '@inquirer/select': 2.5.0 @@ -13882,38 +13903,38 @@ packages: package-json-from-dist: 1.0.1 dev: false - /rollup/4.55.1: - resolution: {integrity: sha512-wDv/Ht1BNHB4upNbK74s9usvl7hObDnvVzknxqY/E/O3X6rW1U1rV1aENEfJ54eFZDTNo7zv1f5N4edCluH7+A==} + /rollup/4.55.3: + resolution: {integrity: sha512-y9yUpfQvetAjiDLtNMf1hL9NXchIJgWt6zIKeoB+tCd3npX08Eqfzg60V9DhIGVMtQ0AlMkFw5xa+AQ37zxnAA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true dependencies: '@types/estree': 1.0.8 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.55.1 - '@rollup/rollup-android-arm64': 4.55.1 - '@rollup/rollup-darwin-arm64': 4.55.1 - '@rollup/rollup-darwin-x64': 4.55.1 - '@rollup/rollup-freebsd-arm64': 4.55.1 - '@rollup/rollup-freebsd-x64': 4.55.1 - '@rollup/rollup-linux-arm-gnueabihf': 4.55.1 - '@rollup/rollup-linux-arm-musleabihf': 4.55.1 - '@rollup/rollup-linux-arm64-gnu': 4.55.1 - '@rollup/rollup-linux-arm64-musl': 4.55.1 - '@rollup/rollup-linux-loong64-gnu': 4.55.1 - '@rollup/rollup-linux-loong64-musl': 4.55.1 - '@rollup/rollup-linux-ppc64-gnu': 4.55.1 - '@rollup/rollup-linux-ppc64-musl': 4.55.1 - '@rollup/rollup-linux-riscv64-gnu': 4.55.1 - '@rollup/rollup-linux-riscv64-musl': 4.55.1 - '@rollup/rollup-linux-s390x-gnu': 4.55.1 - '@rollup/rollup-linux-x64-gnu': 4.55.1 - '@rollup/rollup-linux-x64-musl': 4.55.1 - '@rollup/rollup-openbsd-x64': 4.55.1 - '@rollup/rollup-openharmony-arm64': 4.55.1 - '@rollup/rollup-win32-arm64-msvc': 4.55.1 - '@rollup/rollup-win32-ia32-msvc': 4.55.1 - '@rollup/rollup-win32-x64-gnu': 4.55.1 - '@rollup/rollup-win32-x64-msvc': 4.55.1 + '@rollup/rollup-android-arm-eabi': 4.55.3 + '@rollup/rollup-android-arm64': 4.55.3 + '@rollup/rollup-darwin-arm64': 4.55.3 + '@rollup/rollup-darwin-x64': 4.55.3 + '@rollup/rollup-freebsd-arm64': 4.55.3 + '@rollup/rollup-freebsd-x64': 4.55.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.55.3 + '@rollup/rollup-linux-arm-musleabihf': 4.55.3 + '@rollup/rollup-linux-arm64-gnu': 4.55.3 + '@rollup/rollup-linux-arm64-musl': 4.55.3 + '@rollup/rollup-linux-loong64-gnu': 4.55.3 + '@rollup/rollup-linux-loong64-musl': 4.55.3 + '@rollup/rollup-linux-ppc64-gnu': 4.55.3 + '@rollup/rollup-linux-ppc64-musl': 4.55.3 + '@rollup/rollup-linux-riscv64-gnu': 4.55.3 + '@rollup/rollup-linux-riscv64-musl': 4.55.3 + '@rollup/rollup-linux-s390x-gnu': 4.55.3 + '@rollup/rollup-linux-x64-gnu': 4.55.3 + '@rollup/rollup-linux-x64-musl': 4.55.3 + '@rollup/rollup-openbsd-x64': 4.55.3 + '@rollup/rollup-openharmony-arm64': 4.55.3 + '@rollup/rollup-win32-arm64-msvc': 4.55.3 + '@rollup/rollup-win32-ia32-msvc': 4.55.3 + '@rollup/rollup-win32-x64-gnu': 4.55.3 + '@rollup/rollup-win32-x64-msvc': 4.55.3 fsevents: 2.3.3 dev: false @@ -14202,7 +14223,7 @@ packages: '@sinonjs/commons': 3.0.1 '@sinonjs/fake-timers': 11.3.1 '@sinonjs/samsam': 8.0.3 - diff: 5.2.0 + diff: 5.2.2 nise: 5.1.9 supports-color: 7.2.0 dev: true @@ -14643,17 +14664,15 @@ packages: engines: {node: '>=6'} dev: true - /tar/6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me + /tar/7.5.6: + resolution: {integrity: sha512-xqUeu2JAIJpXyvskvU3uvQW8PAmHrtXp2KDuMJwQqW8Sqq0CaZBAQ+dKS3RBXVhU4wC5NjAdKrmh84241gO9cA==} + engines: {node: '>=18'} dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 + '@isaacs/fs-minipass': 4.0.1 + chownr: 3.0.0 + minipass: 7.1.2 + minizlib: 3.1.0 + yallist: 5.0.0 dev: false /temp-path/1.0.0: @@ -14906,7 +14925,7 @@ packages: acorn-walk: 8.3.4 arg: 4.1.3 create-require: 1.1.1 - diff: 4.0.2 + diff: 4.0.4 make-error: 1.3.6 typescript: 5.9.3 v8-compile-cache-lib: 3.0.1 @@ -14937,7 +14956,7 @@ packages: acorn-walk: 8.3.4 arg: 4.1.3 create-require: 1.1.1 - diff: 4.0.2 + diff: 4.0.4 make-error: 1.3.6 typescript: 4.9.5 v8-compile-cache-lib: 3.0.1 @@ -14967,7 +14986,7 @@ packages: acorn-walk: 8.3.4 arg: 4.1.3 create-require: 1.1.1 - diff: 4.0.2 + diff: 4.0.4 make-error: 1.3.6 typescript: 4.9.5 v8-compile-cache-lib: 3.0.1 @@ -14982,7 +15001,7 @@ packages: typescript: '>=2.7' dependencies: arg: 4.1.3 - diff: 4.0.2 + diff: 4.0.4 make-error: 1.3.6 source-map-support: 0.5.21 typescript: 4.9.5 @@ -15157,66 +15176,66 @@ packages: resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} dev: false - /typescript-eslint/8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji: - resolution: {integrity: sha512-xHURCQNxZ1dsWn0sdOaOfCSQG0HKeqSj9OexIxrz6ypU6wHYOdX2I3D2b8s8wFSsSOYJb+6q283cLiLlkEsBYw==} + /typescript-eslint/8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji: + resolution: {integrity: sha512-gB+EVQfP5RDElh9ittfXlhZJdjSU4jUSTyE2+ia8CYyNvet4ElfaLlAIqDvQV9JPknKx0jQH1racTYe/4LaLSg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/eslint-plugin': 8.53.0_dca5iuiroy2vtdg3rzjjbhb4hm - '@typescript-eslint/parser': 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji - '@typescript-eslint/typescript-estree': 8.53.0_typescript@4.9.5 - '@typescript-eslint/utils': 8.53.0_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/eslint-plugin': 8.53.1_pakcvjk7ygtc4zwskulha7s734 + '@typescript-eslint/parser': 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji + '@typescript-eslint/typescript-estree': 8.53.1_typescript@4.9.5 + '@typescript-eslint/utils': 8.53.1_avq3eyf5kaj6ssrwo7fvkrwnji eslint: 8.57.1 typescript: 4.9.5 transitivePeerDependencies: - supports-color dev: true - /typescript-eslint/8.53.0_eslint@7.32.0: - resolution: {integrity: sha512-xHURCQNxZ1dsWn0sdOaOfCSQG0HKeqSj9OexIxrz6ypU6wHYOdX2I3D2b8s8wFSsSOYJb+6q283cLiLlkEsBYw==} + /typescript-eslint/8.53.1_eslint@7.32.0: + resolution: {integrity: sha512-gB+EVQfP5RDElh9ittfXlhZJdjSU4jUSTyE2+ia8CYyNvet4ElfaLlAIqDvQV9JPknKx0jQH1racTYe/4LaLSg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/eslint-plugin': 8.53.0_t2s57xm67hp4nmvbkcu6rjdgci - '@typescript-eslint/parser': 8.53.0_eslint@7.32.0 - '@typescript-eslint/typescript-estree': 8.53.0 - '@typescript-eslint/utils': 8.53.0_eslint@7.32.0 + '@typescript-eslint/eslint-plugin': 8.53.1_7f3ev5f4rgmdwp43lafel2uhym + '@typescript-eslint/parser': 8.53.1_eslint@7.32.0 + '@typescript-eslint/typescript-estree': 8.53.1 + '@typescript-eslint/utils': 8.53.1_eslint@7.32.0 eslint: 7.32.0 transitivePeerDependencies: - supports-color dev: true - /typescript-eslint/8.53.0_eslint@8.57.1: - resolution: {integrity: sha512-xHURCQNxZ1dsWn0sdOaOfCSQG0HKeqSj9OexIxrz6ypU6wHYOdX2I3D2b8s8wFSsSOYJb+6q283cLiLlkEsBYw==} + /typescript-eslint/8.53.1_eslint@8.57.1: + resolution: {integrity: sha512-gB+EVQfP5RDElh9ittfXlhZJdjSU4jUSTyE2+ia8CYyNvet4ElfaLlAIqDvQV9JPknKx0jQH1racTYe/4LaLSg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/eslint-plugin': 8.53.0_xxyirjqvxmya52bar37s3rf4zi - '@typescript-eslint/parser': 8.53.0_eslint@8.57.1 - '@typescript-eslint/typescript-estree': 8.53.0 - '@typescript-eslint/utils': 8.53.0_eslint@8.57.1 + '@typescript-eslint/eslint-plugin': 8.53.1_2552pu7bmmaqmdrlq4uwpduy5y + '@typescript-eslint/parser': 8.53.1_eslint@8.57.1 + '@typescript-eslint/typescript-estree': 8.53.1 + '@typescript-eslint/utils': 8.53.1_eslint@8.57.1 eslint: 8.57.1 transitivePeerDependencies: - supports-color dev: true - /typescript-eslint/8.53.0_k2rwabtyo525wwqr6566umnmhy: - resolution: {integrity: sha512-xHURCQNxZ1dsWn0sdOaOfCSQG0HKeqSj9OexIxrz6ypU6wHYOdX2I3D2b8s8wFSsSOYJb+6q283cLiLlkEsBYw==} + /typescript-eslint/8.53.1_k2rwabtyo525wwqr6566umnmhy: + resolution: {integrity: sha512-gB+EVQfP5RDElh9ittfXlhZJdjSU4jUSTyE2+ia8CYyNvet4ElfaLlAIqDvQV9JPknKx0jQH1racTYe/4LaLSg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' dependencies: - '@typescript-eslint/eslint-plugin': 8.53.0_zpj3n5bnn5jlhekjw5lfewwpsi - '@typescript-eslint/parser': 8.53.0_k2rwabtyo525wwqr6566umnmhy - '@typescript-eslint/typescript-estree': 8.53.0_typescript@5.9.3 - '@typescript-eslint/utils': 8.53.0_k2rwabtyo525wwqr6566umnmhy + '@typescript-eslint/eslint-plugin': 8.53.1_pyvuimufhdaxzjwomxqp7i7ijm + '@typescript-eslint/parser': 8.53.1_k2rwabtyo525wwqr6566umnmhy + '@typescript-eslint/typescript-estree': 8.53.1_typescript@5.9.3 + '@typescript-eslint/utils': 8.53.1_k2rwabtyo525wwqr6566umnmhy eslint: 8.57.1 typescript: 5.9.3 transitivePeerDependencies: @@ -15657,8 +15676,9 @@ packages: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} dev: true - /yallist/4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + /yallist/5.0.0: + resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} + engines: {node: '>=18'} dev: false /yargs-parser/18.1.3: