@boltic/cli
Version:
A powerful CLI tool for managing Boltic Workflow integrations - create, sync, test, and publish integrations with ease
243 lines (215 loc) • 6.29 kB
JavaScript
import chalk from "chalk";
import fs from "fs";
import isEmpty from "lodash.isempty";
import path from "path";
import {
authentication,
base,
resource1,
webhook,
} from "../templates/schemas.js";
export const createIntegrationFolderStructure = async (
integration,
create_catalogue
) => {
const { id, name, description, icon, activity_type, trigger_type, meta } =
integration;
const spec = {
id,
name,
description,
icon,
activity_type,
trigger_type,
meta,
};
// Create integration folder structure
const integrationName = name.toLowerCase().replace(/\s+/g, "-");
const integrationDir = path.join(process.cwd(), integrationName);
// Ensure the integration directory doesn't exist
if (fs.existsSync(integrationDir)) {
console.log(
chalk.yellow(
`\nWarning: Directory ${integrationDir} already exists!`
)
);
return integrationDir;
}
// Create main directory
fs.mkdirSync(integrationDir, { recursive: true });
// Create schemas directory and its subdirectories
const schemasDir = path.join(integrationDir, "schemas");
const resourcesDir = path.join(schemasDir, "resources");
fs.mkdirSync(resourcesDir, { recursive: true });
const docsDir = path.join(integrationDir, "documentation");
fs.mkdirSync(docsDir, { recursive: true });
// Create template files
const files = {
"schemas/resources/resource1.json": JSON.stringify(resource1, null, 4),
...(create_catalogue && {
"schemas/authentication.json": JSON.stringify(
authentication,
null,
4
),
}),
"schemas/base.json": JSON.stringify(
base(name, create_catalogue),
null,
4
),
...(!isEmpty(trigger_type) && {
"schemas/webhook.json": JSON.stringify(webhook(name), null, 4),
}),
"spec.json": JSON.stringify(spec, null, 4),
...(create_catalogue && {
"Authentication.mdx": `# ${name} Authentication`,
}),
// Documentation files (new structure)
...(!isEmpty(activity_type) && {
"documentation/integration.mdx": `# ${name} Integration`,
}),
...(trigger_type === "CloudTrigger" && {
"documentation/trigger.mdx": `# ${name} Trigger`,
}),
};
// Create all files
for (const [filePath, content] of Object.entries(files)) {
const fullPath = path.join(integrationDir, filePath);
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
fs.writeFileSync(fullPath, content);
}
console.log(chalk.cyan(`To navigate to your integration folder, run:\n`));
console.log(chalk.white(` cd ${integrationName}\n`));
};
export const createExistingIntegrationsFolder = async (payload) => {
const {
integration,
authentication = {},
webhook = {},
configuration = {},
resources = [],
operations = [],
} = payload || {};
// Validate required payload fields early to prevent null dereferences
if (!integration || !integration.name) {
console.error(
chalk.red(
"\n❌ Invalid integration payload received. Missing integration or name."
)
);
return false;
}
const {
id,
name,
description,
icon,
activity_type,
trigger_type,
documentation,
meta,
} = integration;
const spec = {
id,
name,
description,
icon,
activity_type,
trigger_type,
meta,
};
const integrationName = name.toLowerCase().replace(/\s+/g, "-");
const integrationDir = path.join(process.cwd(), integrationName);
// Log if the directory already exists
if (fs.existsSync(integrationDir)) {
console.log(
chalk.yellow(
`\nNotice: Directory ${integrationDir} already exists. Updating contents...\n`
)
);
} else {
console.log(
chalk.green(`\nCreating integration directory: ${integrationDir}\n`)
);
}
// Ensure all necessary folders exist
fs.mkdirSync(integrationDir, { recursive: true });
const schemasDir = path.join(integrationDir, "schemas");
const resourcesDir = path.join(schemasDir, "resources");
fs.mkdirSync(resourcesDir, { recursive: true });
const docsDir = path.join(integrationDir, "documentation");
fs.mkdirSync(docsDir, { recursive: true });
const authentication_documentation = authentication?.documentation || "";
const isDocumentationObject =
documentation &&
typeof documentation === "object" &&
!Array.isArray(documentation);
// Define files and content
const files = {
...(authentication && {
"schemas/authentication.json": JSON.stringify(
authentication?.content || {},
null,
4
),
}),
"schemas/base.json": JSON.stringify(
configuration?.content || {},
null,
4
),
"schemas/webhook.json": JSON.stringify(webhook?.content || {}, null, 4),
"spec.json": JSON.stringify(spec, null, 4),
...(authentication && {
"Authentication.mdx": authentication_documentation || "",
}),
...(!isEmpty(activity_type) && {
"documentation/integration.mdx": isDocumentationObject
? documentation?.integration || `# ${name} Integration`
: (typeof documentation === "string" && documentation) ||
`# ${name} Integration`,
}),
...(trigger_type === "CloudTrigger" && {
"documentation/trigger.mdx": isDocumentationObject
? documentation?.trigger || `# ${name} Trigger`
: `# ${name} Trigger`,
}),
};
// Write resource files
resources.forEach((resource) => {
const resource_id = resource.id;
const resourceName = resource.name.toLowerCase().replace(/\s+/g, "-");
const resourcePath = path.join(resourcesDir, `${resourceName}.json`);
const resourceOperations = (operations || []).filter(
(operation) => operation.resource_id === resource_id
);
const operationsContent = resourceOperations.reduce(
(acc, operation) => {
const operationName = operation.name
.toLowerCase()
.replace(/\s+/g, "-");
acc[operationName] = operation?.content;
return acc;
},
{}
);
const resourceFileContent = {
...resource?.content,
...operationsContent,
};
fs.writeFileSync(
resourcePath,
JSON.stringify(resourceFileContent, null, 4)
);
});
// Write or overwrite all defined files
for (const [filePath, content] of Object.entries(files)) {
const fullPath = path.join(integrationDir, filePath);
fs.mkdirSync(path.dirname(fullPath), { recursive: true });
fs.writeFileSync(fullPath, content);
}
console.log(chalk.cyan(`\nIntegration folder is ready at:`));
console.log(chalk.white(` ${integrationDir}\n`));
return true;
};