patch_template_variables.js (139 lines of code) (raw):
import { readFileSync, writeFile } from 'fs';
import path from 'path';
const workflowSuffix = '_#workflowname#';
const foldersPath = process.argv.slice(2);
const patchTemplateVariables = async (workflowFolderPath, workflowManifest) => {
const manifestFilePath = `./${workflowFolderPath}/manifest.json`;
const workflowFilePath = `./${workflowFolderPath}/workflow.json`;
const workflow = getFileContentInJSON(workflowFilePath);
console.log(`[${workflowFolderPath}] Patching parameter and connection names...`);
const { manifest: updatedManifest, workflow: updatedWorkflow } = await updateConnections(workflowManifest, JSON.stringify(workflow));
const { manifest: finalUpdatedManifest, workflow: finalUpdatedWorkflow} = await updateParameters(updatedManifest, updatedWorkflow);
writeFile(manifestFilePath, JSON.stringify(finalUpdatedManifest, null, 4), () => {});
writeFile(workflowFilePath, JSON.stringify(JSON.parse(finalUpdatedWorkflow), null, 4), () => {});
console.log(`[${workflowFolderPath}] Successfully patched parameter and connection names.`);
};
const verifyMultiWorkflowConnections = (combinedConnections, workflowConnections, workflowFolderPath) => {
for (const [workflowConnectionKey, workflowConnection] of Object.entries(workflowConnections)) {
const existingConnectionWithKey = combinedConnections[workflowConnectionKey];
if (existingConnectionWithKey) {
const isConnectorIdDifferent = existingConnectionWithKey.connectorId !== workflowConnection.connectorId;
const isKindDifferent = existingConnectionWithKey.kind !== workflowConnection.kind;
if (isConnectorIdDifferent || isKindDifferent) {
console.error(`[${workflowFolderPath}] *Connection validation failed. Connection with key ${workflowConnectionKey} exists with different values:
${
isConnectorIdDifferent ? `connectorId: ${existingConnectionWithKey.connectorId}, ${workflowConnection.connectorId}. ` : ''
}${
isKindDifferent ? `kind: ${existingConnectionWithKey.kind}, ${workflowConnection.kind}.` : ''}\nPlease make sure the connection keys are unique.`);
}
}
combinedConnections[workflowConnectionKey] = workflowConnection;
}
}
const verifyMultiWorkflowParameters = (combinedParameters, workflowParameters, workflowFolderPath) => {
for (const workflowParameter of workflowParameters) {
const existingParameterWithName = combinedParameters[workflowParameter.name];
if (existingParameterWithName) {
const isDisplayNameDifferent = existingParameterWithName.displayName !== workflowParameter.displayName;
const isTypeDifferent = existingParameterWithName.type !== workflowParameter.type;
const isDescriptionDifferent = existingParameterWithName.description !== workflowParameter.description;
const isRequiredDifferent = existingParameterWithName.required !== workflowParameter.required;
if (isDisplayNameDifferent || isTypeDifferent || isDescriptionDifferent || isRequiredDifferent) {
console.error(`[${workflowFolderPath}] *Parameter validation failed. Parameters with name ${workflowParameter.name} exists with different values:
${
isDisplayNameDifferent ? `displayName: ${existingParameterWithName.displayName}, ${workflowParameter.displayName}. ` : ''
}${
isTypeDifferent ? `type: ${existingParameterWithName.type}, ${workflowParameter.type}. ` : ''}${
isDescriptionDifferent ? `description: ${existingParameterWithName.description}, ${workflowParameter.description}. ` : ''}${
isRequiredDifferent ? `required: ${existingParameterWithName.required}, ${workflowParameter.required}. ` : ''}\nPlease make sure the parameter names are unique.`);
}
}
combinedParameters[workflowParameter.name] = workflowParameter;
}
}
const run = async () => {
if (foldersPath.length === 0) {
console.error('There are no template folders specified. Please provide the folders with spaces for multiple template folders, example `npm run patchTemplate folder1 folder2 folder3`');
return;
}
console.log("------------Starting patching templates------------");
// 1) Patching parameter and connection names with suffix for all workflows
for (const templateId of foldersPath) {
const workflowManifests = {};
const templateManifestFilePath = `./${templateId}/manifest.json`;
const templateManifest = getFileContentInJSON(templateManifestFilePath);
const combinedConnections = {};
const combinedParameters = {};
const templateWorkflowKeys = Object.keys(templateManifest.workflows);
const isMultiWorkflow = templateWorkflowKeys.length > 1;
for (const workflowId of templateWorkflowKeys) {
const workflowManifestFilePath = `./${templateId}/${workflowId}/manifest.json`;
const workflowManifest = getFileContentInJSON(workflowManifestFilePath);
await patchTemplateVariables(`${templateId}/${workflowId}`, workflowManifest);
workflowManifests[workflowId] = workflowManifest;
}
if (isMultiWorkflow) {
for (const workflowId of templateWorkflowKeys) {
verifyMultiWorkflowConnections(combinedConnections, workflowManifests[workflowId]?.connections, `${templateId}/${workflowId}`);
verifyMultiWorkflowParameters(combinedParameters, workflowManifests[workflowId]?.parameters, `${templateId}/${workflowId}`);
}
}
}
console.log("------------Completed patching templates with suffix------------");
};
const updateConnections = async (manifest, workflow) => {
const updatedConnections = { ...manifest.connections };
for (const name of Object.keys(manifest.connections)) {
const connection = manifest.connections[name];
if (connection.kind?.toLowerCase() === 'shared') {
connection.connectorId = sanitizeConnectorId(connection.connectorId);
}
if (name.endsWith(workflowSuffix)) {
const oldName = name?.split(workflowSuffix)?.[0];
workflow = workflow.replaceAll(`"${oldName}"`, `"${name}"`);
} else {
const newName = `${name}${workflowSuffix}`;
workflow = workflow.replaceAll(`"${name}"`, `"${newName}"`);
updatedConnections[newName] = connection;
delete updatedConnections[name];
}
}
manifest.connections = updatedConnections;
return { manifest, workflow };
};
const updateParameters = async (manifest, workflow) => {
const updatedParameters = [];
for (const parameter of manifest.parameters) {
const name = parameter.name;
if (name.endsWith(workflowSuffix)) {
const oldName = name?.split(workflowSuffix)?.[0];
workflow = workflow.replaceAll(`parameters('${oldName}')`, `parameters('${name}')`);
} else {
const newName = `${name}${workflowSuffix}`;
workflow = workflow.replaceAll(`parameters('${name}')`, `parameters('${newName}')`);
parameter.name = newName;
}
updatedParameters.push(parameter);
}
manifest.parameters = updatedParameters;
return { manifest, workflow };
};
const sanitizeConnectorId = (connectorId) => {
connectorId = (connectorId ?? '').startsWith('/') ? connectorId : `/${connectorId}`;
const fields = connectorId.split('/');
if (fields.length !== 9) {
return connectorId;
}
if (fields[1] === 'subscriptions') {
fields[2] = '#subscription#'
}
if (fields[5] === 'locations') {
fields[6] = '#location#';
}
return fields.join('/');
};
const getFileContentInJSON = (filePath) => {
return JSON.parse(readFileSync(path.resolve(filePath), {
encoding: 'utf-8'
}));
};
run();