diff --git a/package-lock.json b/package-lock.json index 92d24b13..5076e7c3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "chalk": "^5.3.0", "node-stream-zip": "^1.15.0", "open": "^10.1.0", + "ora": "^8.1.0", "ts-pattern": "^5.3.1", "yargs": "^17.7.2", "zod": "^3.23.8", @@ -2318,6 +2319,39 @@ "node": ">=20" } }, + "node_modules/@kontent-ai/migration-toolkit/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@kontent-ai/migration-toolkit/node_modules/cli-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@kontent-ai/migration-toolkit/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, "node_modules/@kontent-ai/migration-toolkit/node_modules/mime": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/mime/-/mime-4.0.4.tgz", @@ -2332,6 +2366,29 @@ "node": ">=16" } }, + "node_modules/@kontent-ai/migration-toolkit/node_modules/ora": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz", + "integrity": "sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==", + "license": "MIT", + "dependencies": { + "chalk": "^5.3.0", + "cli-cursor": "^4.0.0", + "cli-spinners": "^2.9.2", + "is-interactive": "^2.0.0", + "is-unicode-supported": "^2.0.0", + "log-symbols": "^6.0.0", + "stdin-discarder": "^0.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@kontent-ai/migration-toolkit/node_modules/p-limit": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.1.0.tgz", @@ -2346,6 +2403,54 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@kontent-ai/migration-toolkit/node_modules/restore-cursor": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@kontent-ai/migration-toolkit/node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@kontent-ai/migration-toolkit/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/@kontent-ai/migration-toolkit/node_modules/yocto-queue": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz", @@ -4142,14 +4247,15 @@ "peer": true }, "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", + "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "license": "MIT", "dependencies": { - "restore-cursor": "^4.0.0" + "restore-cursor": "^5.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -8804,6 +8910,18 @@ "node": ">=6" } }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -9130,18 +9248,19 @@ } }, "node_modules/ora": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-8.0.1.tgz", - "integrity": "sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/ora/-/ora-8.1.0.tgz", + "integrity": "sha512-GQEkNkH/GHOhPFXcqZs3IDahXEQcQxsSjEkK4KvEEST4t7eNzoMjxTzef+EZ+JluDEV+Raoi3WQ2CflnRdSVnQ==", + "license": "MIT", "dependencies": { "chalk": "^5.3.0", - "cli-cursor": "^4.0.0", + "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", - "stdin-discarder": "^0.2.1", - "string-width": "^7.0.0", + "stdin-discarder": "^0.2.2", + "string-width": "^7.2.0", "strip-ansi": "^7.1.0" }, "engines": { @@ -9774,20 +9893,48 @@ } }, "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", + "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", + "license": "MIT", "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" + "onetime": "^7.0.0", + "signal-exit": "^4.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor/node_modules/onetime": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", + "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", diff --git a/package.json b/package.json index 4c84bf9c..5e492e70 100644 --- a/package.json +++ b/package.json @@ -51,6 +51,7 @@ "chalk": "^5.3.0", "node-stream-zip": "^1.15.0", "open": "^10.1.0", + "ora": "^8.1.0", "ts-pattern": "^5.3.1", "yargs": "^17.7.2", "zod": "^3.23.8", @@ -70,4 +71,4 @@ "uuid": "^9.0.1", "vitest": "^2.1.1" } -} \ No newline at end of file +} diff --git a/src/modules/sync/constants/emojiCodes.ts b/src/modules/sync/constants/emojiCodes.ts new file mode 100644 index 00000000..5906afeb --- /dev/null +++ b/src/modules/sync/constants/emojiCodes.ts @@ -0,0 +1 @@ +export const noSyncTaskEmoji = "\u{2728}"; diff --git a/src/modules/sync/sync/assetFolders.ts b/src/modules/sync/sync/assetFolders.ts index 6126dfb5..bc54ed2a 100644 --- a/src/modules/sync/sync/assetFolders.ts +++ b/src/modules/sync/sync/assetFolders.ts @@ -1,4 +1,5 @@ import { AssetFolderModels, ManagementClient } from "@kontent-ai/management-sdk"; +import { oraPromise } from "ora"; import { match } from "ts-pattern"; import { logError, logInfo, LogOptions } from "../../../log.js"; @@ -6,6 +7,7 @@ import { handleKontentErrors, throwError } from "../../../utils/error.js"; import { apply, not } from "../../../utils/function.js"; import { omit } from "../../../utils/object.js"; import { serially } from "../../../utils/requests.js"; +import { noSyncTaskEmoji } from "../constants/emojiCodes.js"; import { DiffModel } from "../types/diffModel.js"; import { getTargetCodename, PatchOperation } from "../types/patchOperation.js"; import { isOp } from "./utils.js"; @@ -16,29 +18,30 @@ export const syncAssetFolders = async ( logOptions: LogOptions, ) => { if (!operations.length) { - logInfo(logOptions, "standard", "No asset folders updates"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji}No asset folders updates.`); return; } - logInfo(logOptions, "standard", "Updating asset folders"); - const removeOps = operations.filter(isOp("remove")); - await serially(removeOps.map(operation => () => - client - .modifyAssetFolders() - .withData([convertOperation(operation)]) - .toPromise() - .catch(handleKontentErrors(err => { - logError( - logOptions, - "error", - `Failed to remove asset folder "${operation.path}" error: ${JSON.stringify(err)}. Skipping it.`, - ); + await oraPromise( + serially(removeOps.map(operation => () => + client + .modifyAssetFolders() + .withData([convertOperation(operation)]) + .toPromise() + .catch(handleKontentErrors(err => { + logError( + logOptions, + "error", + `Failed to remove asset folder "${operation.path}" error: ${JSON.stringify(err)}. Skipping it.`, + ); - return undefined; - }, [5])) // this is a generic code for invalid body, but the error with folder containing assets unfortunately doesn't have a specific code - )); + return undefined; + }, [5])) // this is a generic code for invalid body, but the error with folder containing assets unfortunately doesn't have a specific code + )), + { text: "Updating asset folders" }, + ); const restOps = operations.filter(not(isOp("remove"))); diff --git a/src/modules/sync/sync/collections.ts b/src/modules/sync/sync/collections.ts index 7e3b6641..adc6f1b9 100644 --- a/src/modules/sync/sync/collections.ts +++ b/src/modules/sync/sync/collections.ts @@ -1,7 +1,9 @@ import { CollectionModels, ManagementClient } from "@kontent-ai/management-sdk"; +import { oraPromise } from "ora"; import { logInfo, LogOptions } from "../../../log.js"; import { omit } from "../../../utils/object.js"; +import { noSyncTaskEmoji } from "../constants/emojiCodes.js"; import { DiffModel } from "../types/diffModel.js"; import { getTargetCodename, PatchOperation } from "../types/patchOperation.js"; @@ -11,16 +13,17 @@ export const syncAddAndReplaceCollections = ( logOptions: LogOptions, ) => { if (!collections.length) { - logInfo(logOptions, "standard", "No collections to add or update"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No collections to add or update`); return Promise.resolve(); } - logInfo(logOptions, "standard", "Adding and updating collections"); - - return client - .setCollections() - .withData(collections.filter(op => op.op !== "remove").map(transformCollectionsReferences)) - .toPromise(); + return oraPromise( + client + .setCollections() + .withData(collections.filter(op => op.op !== "remove").map(transformCollectionsReferences)) + .toPromise(), + { text: "Adding and updating collections" }, + ); }; export const syncRemoveCollections = ( @@ -31,16 +34,19 @@ export const syncRemoveCollections = ( const collectionsRemoveOps = collections.filter(op => op.op === "remove"); if (!collectionsRemoveOps.length) { - logInfo(logOptions, "standard", "No collections to delete"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No collections to delete`); return Promise.resolve(); } - logInfo(logOptions, "standard", "Deleting collections"); - - return client - .setCollections() - .withData(collectionsRemoveOps.map(transformCollectionsReferences)) - .toPromise(); + return oraPromise( + client + .setCollections() + .withData(collectionsRemoveOps.map(transformCollectionsReferences)) + .toPromise(), + { + text: "Deleting collections", + }, + ); }; const transformCollectionsReferences = (operation: PatchOperation): CollectionModels.ISetCollectionData => { diff --git a/src/modules/sync/sync/languages.ts b/src/modules/sync/sync/languages.ts index 12448a54..1b52e7f7 100644 --- a/src/modules/sync/sync/languages.ts +++ b/src/modules/sync/sync/languages.ts @@ -1,4 +1,5 @@ import { LanguageModels, ManagementClient } from "@kontent-ai/management-sdk"; +import { oraPromise } from "ora"; import { match } from "ts-pattern"; import { v4 as createUuid } from "uuid"; import { z } from "zod"; @@ -6,6 +7,7 @@ import { z } from "zod"; import { logInfo, LogOptions } from "../../../log.js"; import { omit } from "../../../utils/object.js"; import { serially } from "../../../utils/requests.js"; +import { noSyncTaskEmoji } from "../constants/emojiCodes.js"; import { DiffModel } from "../types/diffModel.js"; import { PatchOperation } from "../types/patchOperation.js"; @@ -15,15 +17,14 @@ export const syncLanguages = async ( logOptions: LogOptions, ) => { if (operations.added.length) { - logInfo(logOptions, "standard", "Adding languages"); - await serially(operations.added.filter(op => !op.is_default).map(l => () => addLanguage(client, l))); + await oraPromise(serially(operations.added.filter(op => !op.is_default).map(l => () => addLanguage(client, l))), { + text: "Adding languages", + }); } else { - logInfo(logOptions, "standard", "No languages to add"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji}No languages to add`); } if ([...operations.updated].flatMap(([, arr]) => arr).length) { - logInfo(logOptions, "standard", "Updating Languages"); - const transformedOperations = [...operations.updated].map( ([codename, operations]) => [codename, operations.map(transformLanguagePatchOperation)] as const, ); @@ -32,21 +33,25 @@ export const syncLanguages = async ( operationsToOrdNumb(operations) - operationsToOrdNumb(operations2) ); - await serially( - sortedOperations.map(([codename, operations]) => () => modifyLanguage(client, codename, operations)), + await oraPromise( + serially( + sortedOperations.map(([codename, operations]) => () => modifyLanguage(client, codename, operations)), + ), + { text: "Updating Languages" }, ); } else { - logInfo(logOptions, "standard", "No languages to update"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No languages to update`); } if (operations.deleted.size) { - logInfo(logOptions, "standard", "Deactivating languages"); - - await serially( - [...operations.deleted].map(codename => () => deleteLanguage(client, codename)), + await oraPromise( + serially( + [...operations.deleted].map(codename => () => deleteLanguage(client, codename)), + ), + { text: "Deactivating languages" }, ); } else { - logInfo(logOptions, "standard", "No languages to deactivate"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No languages to deactivate`); } }; diff --git a/src/modules/sync/sync/snippets.ts b/src/modules/sync/sync/snippets.ts index 21ab66aa..7958bcb5 100644 --- a/src/modules/sync/sync/snippets.ts +++ b/src/modules/sync/sync/snippets.ts @@ -1,9 +1,11 @@ import { ContentTypeElements, ContentTypeSnippetModels, ManagementClient } from "@kontent-ai/management-sdk"; +import { oraPromise } from "ora"; import { logInfo, LogOptions } from "../../../log.js"; import { omit } from "../../../utils/object.js"; import { serially } from "../../../utils/requests.js"; import { elementTypes } from "../constants/elements.js"; +import { noSyncTaskEmoji } from "../constants/emojiCodes.js"; import { DiffModel } from "../types/diffModel.js"; import { PatchOperation } from "../types/patchOperation.js"; import { @@ -21,12 +23,16 @@ export const addSnippetsWithoutReferences = async ( logOptions: LogOptions, ) => { if (!addSnippets.length) { - logInfo(logOptions, "standard", "No content type snippets to add"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No content type snippets to add`); return; } - logInfo(logOptions, "standard", "Adding content type snippets"); const addSnippetsWithoutReferences = addSnippets.map(removeReferencesFromAddOp); - await serially(addSnippetsWithoutReferences.map(s => () => addSnippet(client, s))); + await oraPromise( + serially(addSnippetsWithoutReferences.map(s => () => addSnippet(client, s))), + { + text: "Adding content type snippets", + }, + ); }; export const addSnippetsReferences = async ( @@ -52,22 +58,24 @@ export const addSnippetsReferences = async ( const snippetsReplaceReferencesOps = addSnippets.map(createUpdateReferencesOps); if (snippetsReplaceReferencesOps.every(([, arr]) => !arr.length)) { - logInfo(logOptions, "standard", "No content type snippet's references to update"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No content type snippet's references to update`); return; } - logInfo(logOptions, "standard", "Updating content type snippet's references"); - await serially( - [...snippetReplaceOpsAddIntoReferencingElements, ...snippetsReplaceReferencesOps].map( - ([codename, operations]) => () => - operations.length - ? updateSnippet( - client, - codename, - operations.map(o => omit(o, ["oldValue"])), - ) - : Promise.resolve(), + await oraPromise( + serially( + [...snippetReplaceOpsAddIntoReferencingElements, ...snippetsReplaceReferencesOps].map( + ([codename, operations]) => () => + operations.length + ? updateSnippet( + client, + codename, + operations.map(o => omit(o, ["oldValue"])), + ) + : Promise.resolve(), + ), ), + { text: "Updating content type snippet's references" }, ); }; @@ -95,17 +103,19 @@ export const addElementsIntoSnippetsWithoutReferences = async ( ); if (addSnippetsOpsWithoutRefs.every(([, ops]) => !ops.length)) { - logInfo(logOptions, "standard", "No elements to add into content type snippets"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No elements to add into content type snippets`); return; } - logInfo(logOptions, "standard", "Adding elements into content type snippets"); - await serially(addSnippetsOpsWithoutRefs.map( - ([codename, operations]) => () => - operations.length - ? updateSnippet(client, codename, operations) - : Promise.resolve(), - )); + await oraPromise( + serially(addSnippetsOpsWithoutRefs.map( + ([codename, operations]) => () => + operations.length + ? updateSnippet(client, codename, operations) + : Promise.resolve(), + )), + { text: "Adding elements into content type snippets" }, + ); }; export const updateSnippets = async ( @@ -117,22 +127,24 @@ export const updateSnippets = async ( .map(([c, ops]) => [c, ops.filter(o => !isOp("addInto")(o))] as const); if (otherSnippetOps.flatMap(([, ops]) => ops).length === 0) { - logInfo(logOptions, "standard", "No content type snippets to update"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No content type snippets to update`); return; } - logInfo(logOptions, "standard", "Updating content type snippets"); - await serially( - otherSnippetOps.map( - ([codename, operations]) => () => - operations.length - ? updateSnippet( - client, - codename, - operations.map(op => "oldValue" in op ? omit(op, ["oldValue"]) : op), - ) - : Promise.resolve(), + await oraPromise( + serially( + otherSnippetOps.map( + ([codename, operations]) => () => + operations.length + ? updateSnippet( + client, + codename, + operations.map(op => "oldValue" in op ? omit(op, ["oldValue"]) : op), + ) + : Promise.resolve(), + ), ), + { text: "Updating content type snippets" }, ); }; @@ -142,10 +154,11 @@ export const deleteContentTypeSnippets = async ( logOptions: LogOptions, ) => { if (snippetOps.deleted.size) { - logInfo(logOptions, "standard", "Deleting content type snippets"); - await serially(Array.from(snippetOps.deleted).map(c => () => deleteSnippet(client, c))); + await oraPromise(serially(Array.from(snippetOps.deleted).map(c => () => deleteSnippet(client, c))), { + text: "Deleting content type snippets", + }); } else { - logInfo(logOptions, "standard", "No content type snippets to delete"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No content type snippets to delete`); } }; diff --git a/src/modules/sync/sync/spaces.ts b/src/modules/sync/sync/spaces.ts index 3c06bef3..d2391930 100644 --- a/src/modules/sync/sync/spaces.ts +++ b/src/modules/sync/sync/spaces.ts @@ -1,9 +1,11 @@ import { ManagementClient, SpaceModels } from "@kontent-ai/management-sdk"; +import { oraPromise } from "ora"; import { match, P } from "ts-pattern"; import { logInfo, LogOptions } from "../../../log.js"; import { throwError } from "../../../utils/error.js"; import { serially } from "../../../utils/requests.js"; +import { noSyncTaskEmoji } from "../constants/emojiCodes.js"; import { DiffModel } from "../types/diffModel.js"; import { PatchOperation } from "../types/patchOperation.js"; @@ -13,44 +15,47 @@ export const syncSpaces = async ( logOptions: LogOptions, ) => { if (model.added.length) { - logInfo(logOptions, "standard", "Adding spaces"); - - await serially(model.added.map(space => () => - client - .addSpace() - .withData(space as SpaceModels.IAddSpaceData) - .toPromise() - )); + await oraPromise( + serially(model.added.map(space => () => + client + .addSpace() + .withData(space as SpaceModels.IAddSpaceData) + .toPromise() + )), + { text: "Adding spaces" }, + ); } else { - logInfo(logOptions, "standard", "No spaces to add"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No spaces to add`); } if ([...model.updated].flatMap(([, arr]) => arr).length) { - logInfo(logOptions, "standard", "Updating spaces"); - - await serially([...model.updated].map(([spaceCodename, operations]) => () => - client - .modifySpace() - .bySpaceCodename(spaceCodename) - .withData(operations.map(convertOperation)) - .toPromise() - )); + await oraPromise( + serially([...model.updated].map(([spaceCodename, operations]) => () => + client + .modifySpace() + .bySpaceCodename(spaceCodename) + .withData(operations.map(convertOperation)) + .toPromise() + )), + { text: "Updating spaces" }, + ); } else { - logInfo(logOptions, "standard", "No spaces to update"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No spaces to update`); } if (model.deleted.size) { - logInfo(logOptions, "standard", "Deleting spaces"); - - await serially([...model.deleted].map(spaceCodename => () => - client - .deleteSpace() - .bySpaceCodename(spaceCodename) - .toPromise() - )); + await oraPromise( + serially([...model.deleted].map(spaceCodename => () => + client + .deleteSpace() + .bySpaceCodename(spaceCodename) + .toPromise() + )), + { text: "Deleting spaces" }, + ); } { - logInfo(logOptions, "standard", "No spaces to delete"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No spaces to delete`); } }; diff --git a/src/modules/sync/sync/taxonomy.ts b/src/modules/sync/sync/taxonomy.ts index d87350cf..f0b8d334 100644 --- a/src/modules/sync/sync/taxonomy.ts +++ b/src/modules/sync/sync/taxonomy.ts @@ -1,7 +1,9 @@ import { ManagementClient, TaxonomyModels } from "@kontent-ai/management-sdk"; +import { oraPromise } from "ora"; import { logInfo, LogOptions } from "../../../log.js"; import { serially } from "../../../utils/requests.js"; +import { noSyncTaskEmoji } from "../constants/emojiCodes.js"; import { DiffModel } from "../types/diffModel.js"; import { getTargetCodename, PatchOperation } from "../types/patchOperation.js"; @@ -11,34 +13,38 @@ export const syncTaxonomies = async ( logOptions: LogOptions, ) => { if (taxonomies.added.length) { - logInfo(logOptions, "standard", "Adding taxonomies"); - await serially(taxonomies.added.map(g => () => addTaxonomyGroup(client, g))); + await oraPromise(serially(taxonomies.added.map(g => () => addTaxonomyGroup(client, g))), { + text: "Adding taxonomies", + }); } else { - logInfo(logOptions, "standard", "No taxonomies to add"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No taxonomies to add`); } if ([...taxonomies.updated].flatMap(([, arr]) => arr).length) { - logInfo(logOptions, "standard", "Updating taxonomies"); - await serially( - Array.from(taxonomies.updated.entries()).map(([codename, operations]) => () => - operations.length - ? updateTaxonomyGroup( - client, - codename, - operations.map(transformTaxonomyOperations), - ) - : Promise.resolve() + await oraPromise( + serially( + Array.from(taxonomies.updated.entries()).map(([codename, operations]) => () => + operations.length + ? updateTaxonomyGroup( + client, + codename, + operations.map(transformTaxonomyOperations), + ) + : Promise.resolve() + ), ), + { text: "Updating taxonomies" }, ); } else { - logInfo(logOptions, "standard", "No taxonomies to update"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No taxonomies to update`); } if (taxonomies.deleted.size) { - logInfo(logOptions, "standard", "Deleting taxonomies"); - await serially(Array.from(taxonomies.deleted).map(c => () => deleteTaxonomyGroup(client, c))); + await oraPromise(serially(Array.from(taxonomies.deleted).map(c => () => deleteTaxonomyGroup(client, c))), { + text: "Deleting taxonomies", + }); } else { - logInfo(logOptions, "standard", "No taxonomies to delete"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No taxonomies to delete`); } }; diff --git a/src/modules/sync/sync/types.ts b/src/modules/sync/sync/types.ts index 33f23e1f..4f5073df 100644 --- a/src/modules/sync/sync/types.ts +++ b/src/modules/sync/sync/types.ts @@ -1,8 +1,10 @@ import { ContentTypeModels, ManagementClient } from "@kontent-ai/management-sdk"; +import { oraPromise } from "ora"; import { logInfo, LogOptions } from "../../../log.js"; import { omit } from "../../../utils/object.js"; import { serially } from "../../../utils/requests.js"; +import { noSyncTaskEmoji } from "../constants/emojiCodes.js"; import { DiffModel } from "../types/diffModel.js"; import { createUpdateReferencesOps, removeReferencesFromAddOp } from "./utils.js"; @@ -14,12 +16,13 @@ export const addTypesWithoutReferences = async ( const addTypesWithoutReferences = addContentTypes.map(removeReferencesFromAddOp); if (!addTypesWithoutReferences.length) { - logInfo(logOptions, "standard", "No content types to add"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No content types to add`); return; } - logInfo(logOptions, "standard", "Adding content types"); - await serially(addTypesWithoutReferences.map(t => () => addContentType(client, t))); + await oraPromise(serially(addTypesWithoutReferences.map(t => () => addContentType(client, t))), { + text: "Adding content types", + }); }; export const updateContentTypesAndAddReferences = async ( @@ -30,25 +33,27 @@ export const updateContentTypesAndAddReferences = async ( const typesReplaceReferencesOps = typeOps.added.map(createUpdateReferencesOps); if (!typesReplaceReferencesOps.length) { - logInfo(logOptions, "standard", "No content types to update"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No content types to update`); return; } - logInfo(logOptions, "standard", "Updating content types and adding their references"); - await serially( - [...typeOps.updated.entries(), ...typesReplaceReferencesOps].map(([codename, operations]) => () => - operations.length - ? updateContentType( - client, - codename, - operations.map(o => - o.op === "replace" || o.op === "remove" - ? omit(o, ["oldValue"]) - : o as unknown as ContentTypeModels.IModifyContentTypeData - ), - ) - : Promise.resolve() + await oraPromise( + serially( + [...typeOps.updated.entries(), ...typesReplaceReferencesOps].map(([codename, operations]) => () => + operations.length + ? updateContentType( + client, + codename, + operations.map(o => + o.op === "replace" || o.op === "remove" + ? omit(o, ["oldValue"]) + : o as unknown as ContentTypeModels.IModifyContentTypeData + ), + ) + : Promise.resolve() + ), ), + { text: "Updating content types and adding their references" }, ); }; @@ -58,10 +63,11 @@ export const deleteContentTypes = async ( logOptions: LogOptions, ) => { if (typeOps.deleted.size) { - logInfo(logOptions, "standard", "Deleting content types"); - await serially(Array.from(typeOps.deleted).map(c => () => deleteContentType(client, c))); + await oraPromise(serially(Array.from(typeOps.deleted).map(c => () => deleteContentType(client, c))), { + text: "Deleting content types", + }); } else { - logInfo(logOptions, "standard", "No content types to delete"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No content types to delete`); } }; diff --git a/src/modules/sync/sync/webSpotlight.ts b/src/modules/sync/sync/webSpotlight.ts index b22302f6..ce01fbd2 100644 --- a/src/modules/sync/sync/webSpotlight.ts +++ b/src/modules/sync/sync/webSpotlight.ts @@ -1,7 +1,9 @@ import { ManagementClient } from "@kontent-ai/management-sdk"; +import { oraPromise } from "ora"; import { match, P } from "ts-pattern"; import { logInfo, LogOptions } from "../../../log.js"; +import { noSyncTaskEmoji } from "../constants/emojiCodes.js"; import { WebSpotlightDiffModel } from "../types/diffModel.js"; export const updateWebSpotlight = ( @@ -11,18 +13,19 @@ export const updateWebSpotlight = ( ): Promise => match(diffModel) .with({ change: "none" }, () => { - logInfo(logOptions, "standard", "No web spotlight changes to perform"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No web spotlight changes to perform`); return Promise.resolve(); }) .with({ change: "deactivate" }, () => { - logInfo(logOptions, "standard", "Deactivating web spotlight"); - return client.deactivateWebSpotlight().toPromise(); + return oraPromise(client.deactivateWebSpotlight().toPromise(), { text: "Deactivating web spotlight" }); }) .with( { change: P.union("activate", "changeRootType") }, ws => { - logInfo(logOptions, "standard", "Updating web spotlight"); - return client.activateWebSpotlight().withData({ root_type: { codename: ws.rootTypeCodename } }).toPromise(); + return oraPromise( + client.activateWebSpotlight().withData({ root_type: { codename: ws.rootTypeCodename } }).toPromise(), + { text: "Updating web spotlight" }, + ); }, ) .exhaustive(); diff --git a/src/modules/sync/sync/workflows.ts b/src/modules/sync/sync/workflows.ts index 4c8f02bc..81b90bb8 100644 --- a/src/modules/sync/sync/workflows.ts +++ b/src/modules/sync/sync/workflows.ts @@ -1,8 +1,10 @@ import { ManagementClient, WorkflowModels } from "@kontent-ai/management-sdk"; +import { oraPromise } from "ora"; import { logInfo, LogOptions } from "../../../log.js"; import { throwError } from "../../../utils/error.js"; import { serially } from "../../../utils/requests.js"; +import { noSyncTaskEmoji } from "../constants/emojiCodes.js"; import { DiffModel } from "../types/diffModel.js"; export const syncWorkflows = async ( @@ -11,36 +13,38 @@ export const syncWorkflows = async ( logOptions: LogOptions, ) => { if (operations.added.length) { - logInfo(logOptions, "standard", "Adding workflows"); - await serially(operations.added.map(w => () => addWorkflow(client, w))); + await oraPromise(serially(operations.added.map(w => () => addWorkflow(client, w))), { text: "Adding workflows" }); } else { - logInfo(logOptions, "standard", "No workflows to add"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No workflows to add`); } if ([...operations.updated].flatMap(([, arr]) => arr).length) { - logInfo(logOptions, "standard", "Updating workflows"); - - await serially( - [...operations.updated.keys()].map(codename => () => - modifyWorkflow( - client, - codename, - operations.sourceWorkflows.find(w => w.codename === codename) - ?? throwError(`Workflow { codename: ${codename} } not found.`), - ) + await oraPromise( + serially( + [...operations.updated.keys()].map(codename => () => + modifyWorkflow( + client, + codename, + operations.sourceWorkflows.find(w => w.codename === codename) + ?? throwError(`Workflow { codename: ${codename} } not found.`), + ) + ), ), + { text: "Updating workflows" }, ); } else { - logInfo(logOptions, "standard", "No workflows to update"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No workflows to update`); } if (operations.deleted.size) { - logInfo(logOptions, "standard", "Deleting workflows"); - await serially( - [...operations.deleted].map(codename => () => deleteWorkflow(client, codename)), + await oraPromise( + serially( + [...operations.deleted].map(codename => () => deleteWorkflow(client, codename)), + ), + { text: "Deleting workflows" }, ); } else { - logInfo(logOptions, "standard", "No workflows to delete"); + logInfo(logOptions, "standard", `${noSyncTaskEmoji} No workflows to delete`); } };