Skip to content

Commit

Permalink
CTC-2272 Add migration examples
Browse files Browse the repository at this point in the history
  • Loading branch information
jancerman committed Jun 24, 2024
1 parent 80f4fb8 commit 01c22f6
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 0 deletions.
2 changes: 2 additions & 0 deletions ts/migrate-from-other-systems/install_migration_toolkit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Add the Migration toolkit to your migration project
npm i @kontent-ai-consulting/migration-toolkit --save-dev
36 changes: 36 additions & 0 deletions ts/migrate-from-other-systems/migration_toolkit_boilerplate
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {
ExportAdapter,
MigrationAsset,
MigrationItem,
exportAsync,
importAsync,
} from "@kontent-ai-consulting/migration-toolkit";

// Specifies how to map the exported content to migration objects
const adapter: ExportAdapter = {
name: "customExportAdapter",
exportAsync: () => {
// TODO: Load the exported content and map it to MigrationItems
const migrationItems: MigrationItem[] = [];
// TODO: Load the exported assets and map them to MigrationAssets
const migrationAssets: MigrationAsset[] = [];

return {
items: migrationItems,
assets: migrationAssets,
};
},
};

// Runs the adapter to prepare exported data for import
const exportData = await exportAsync(adapter);

// Imports the exported data to a Kontent.ai environment
await importAsync({
data: exportData,
adapterConfig: {
environmentId: "YOUR_ENVIRONMENT_ID",
apiKey: "YOUR_MANAGEMENT_API_KEY",
skipFailedItems: false,
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {
MigrationAsset,
ExportAdapter,
} from "@kontent-ai-consulting/migration-toolkit";
import { readFileSync } from "fs";

// Adapter specifies how to map the exported content to migration objects
const adapter: ExportAdapter = {
name: "customExportAdapter",
exportAsync: () => {
const sourceAssets = readFileSync("./exported-files.zip");
const migrationAssets: MigrationAsset[] = [];

// Example of mapping exported files to an MigrationAsset
for (const sourceAsset of JSON.parse(sourceAssets)) {
const asset: MigrationAsset = {
// Identifies a file within the exported .zip archive
_zipFilename: sourceAsset.filename,
// Specifies the asset filename to use in Kontent.ai
codename: toCodename(sourceAsset.filename),
filename: sourceAsset.filename,
// Specifies the asset title.
title: sourceAsset.title,
// Specifies the binary file you want to upload and use for the asset
binaryData: readFileSync("./warrior_teaser.jpg"), // TBD
// Specifies alt texts for the asset in multiple languages
descriptions: [
{
description: sourceAsset.altText,
language: {
codename: toLanguage(sourceAsset.altTextLanguage)
}
}
]
};

migrationAssets.push(asset);
}

return {
assets: migrationAssets,
};
},
};

Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import {
MigrationElementModels,
MigrationElements,
MigrationItem,
elementsBuilder,
ExportAdapter,
} from "@kontent-ai-consulting/migration-toolkit";
import { readFileSync } from "fs";

// Defines the elements of the Movie content type in a Kontent.ai project
interface MovieElements extends MigrationElements {
title: MigrationElementModels.TextElement;
plot: MigrationElementModels.RichTextElement;
length: MigrationElementModels.NumberElement;
category: MigrationElementModels.MultipleChoiceElement;
poster: MigrationElementModels.AssetElement;
}

// Defines the structure of the exported content for easier mapping
interface SourceItemModel {
title: string;
language: string;
genre: string;
text: string;
duration: number;
}

// Adapter specifies how to map the exported content to migration objects
const adapter: ExportAdapter = {
name: "customExportAdapter",
exportAsync: () => {
// Load the exported content to 'fileData'
const sourceContent = readFileSync("./exported-content.json").toString();
const migrationItems: MigrationItem[] = [];

// Example of mapping a source item to a typed MigrationItem
for (const item of JSON.parse(sourceContent) as SourceItemModel[]) {
const movie: MigrationItem<MovieElements> = {
system: {
name: item.title,
// TODO: Write a custom function to transform the original title to the Kontent.ai codename format according to https://kontent.ai/learn/docs/apis/openapi/management-api-v2/#section/Rules-for-codenames
codename: toCodename(item.title),
collection: { codename: "default", },
// TODO: Write a custom function to transform the source language identifier to your language codename in Kontent.ai
language: { codename: toLanguage(item.language), },
// Because we're migrating a single type of content, cotent type codename is hardcoded
type: { codename: "movie", },
workflow: { codename: "default", },
workflow_step: { codename: "draft", },
},
elements: {
title: elementsBuilder().textElement({ value: item.title }),
length: elementsBuilder().numberElement({ value: item.duration }),
category: elementsBuilder().multipleChoiceElement({
value: item.genre.split(",").map((m) => {
return { codename: m.trim() };
}),
}),
// Asset element references the file by the asset codename
poster: elementsBuilder().assetElement({
value: [{ codename: "warrior_teaser", },],
}),
// The rich text content in Kontent.ai is an HTML5 fragment that contains structured content
// See https://kontent.ai/learn/docs/apis/openapi/management-api-v2/#section/HTML5-elements-allowed-in-rich-text
plot: elementsBuilder().richTextElement({
value: {
value: `<h1>${item.title}</h1><p>${item.text}</p>`,
components: [],
},
}),
},
};

migrationItems.push(movie);
}

return {
items: migrationItems,
};
},
};

0 comments on commit 01c22f6

Please sign in to comment.