in Composer/packages/lib/indexers/src/utils/lgUtil.ts [85:287]
id: getFileName(item.id),
path: item.id,
description: item.description,
};
});
return {
id,
content,
templates,
allTemplates,
diagnostics,
imports,
options: parseResult.options,
parseResult,
isContentUnparsed: false,
};
}
export function increaseNameUtilNotExist(templates: LgTemplate[], name: string): string {
// if duplicate, increse name with Copy1 Copy2 ...
let repeatIndex = 0;
let newName = name;
while (templates.findIndex((item) => item.name === newName) !== -1) {
repeatIndex += 1;
newName = name + repeatIndex.toString();
}
return newName;
}
export function updateTemplate(
lgFile: LgFile,
templateName: string,
template: { name?: string; parameters?: string[]; body?: string },
importResolver?: ImportResolverDelegate
): LgFile {
const { id } = lgFile;
const { name, parameters, body } = template;
const resource = getLgResource(lgFile, importResolver);
const originTemplate = resource.toArray().find((t) => t.name === templateName);
const templateToUpdate = {
name: name || originTemplate?.name || templateName,
parameters: parameters || originTemplate?.parameters || [],
body: typeof body === 'string' ? body : originTemplate?.body || '',
};
let templates;
// add if not exist
if (!originTemplate) {
templates = resource.addTemplate(templateName, templateToUpdate.parameters, templateToUpdate.body);
// remove if template is null
} else if (!template || isEmpty(template)) {
templates = resource.deleteTemplate(templateName);
} else {
templates = resource.updateTemplate(
templateName,
templateToUpdate.name,
templateToUpdate.parameters,
templateToUpdate.body
);
}
return convertTemplatesToLgFile(id, templates.toString(), templates);
}
// if name exist, throw error.
export function addTemplate(
lgFile: LgFile,
{ name, parameters = [], body }: LgTemplate,
importResolver?: ImportResolverDelegate
): LgFile {
const { id } = lgFile;
const resource = getLgResource(lgFile, importResolver);
const templates = resource.addTemplate(name, parameters, body);
return convertTemplatesToLgFile(id, templates.toString(), templates);
}
export function addTemplates(lgFile: LgFile, templates: LgTemplate[], importResolver?: ImportResolverDelegate): LgFile {
const { id, content } = lgFile;
const resource = Templates.parseText(content, undefined, importResolver);
for (const { name, parameters = [], body } of templates) {
resource.addTemplate(name, parameters, body);
}
return convertTemplatesToLgFile(id, resource.toString(), resource);
}
// if name exist, add it anyway, with name like `${name}1` `${name}2`
export function addTemplateAnyway(
lgFile: LgFile,
{ name = 'TemplateName', parameters = [], body = '-TemplateBody' }: LgTemplate,
importResolver?: ImportResolverDelegate
): LgFile {
const { id } = lgFile;
const resource = getLgResource(lgFile, importResolver);
const newName = increaseNameUtilNotExist(resource.toArray(), name);
const templates = resource.addTemplate(newName, parameters, body);
return convertTemplatesToLgFile(id, templates.toString(), templates);
}
// if toTemplateName exist, throw error.
export function copyTemplate(
lgFile: LgFile,
fromTemplateName: string,
toTemplateName: string,
importResolver?: ImportResolverDelegate
): LgFile {
const { id } = lgFile;
const resource = getLgResource(lgFile, importResolver);
const fromTemplate = resource.toArray().find((t) => t.name === fromTemplateName);
if (!fromTemplate) {
throw new Error(formatMessage('fromTemplateName does not exist'));
}
const { parameters, body } = fromTemplate;
const templates = resource.addTemplate(toTemplateName, parameters, body);
return convertTemplatesToLgFile(id, templates.toString(), templates);
}
// if toTemplateName exist, add it anyway, with name like `${toTemplateName}1` `${toTemplateName}2`
export function copyTemplateAnyway(
lgFile: LgFile,
fromTemplateName: string,
toTemplateName?: string,
importResolver?: ImportResolverDelegate
): LgFile {
const { id } = lgFile;
const resource = getLgResource(lgFile, importResolver);
const fromTemplate = resource.toArray().find((t) => t.name === fromTemplateName);
if (!fromTemplate) {
return convertTemplatesToLgFile(id, resource.toString(), resource);
}
let newName = toTemplateName;
if (!newName) {
const copyName = formatMessage(`{name}_Copy`, { name: fromTemplate.name });
newName = increaseNameUtilNotExist(resource.toArray(), copyName);
}
const { parameters, body } = fromTemplate;
const templates = resource.addTemplate(newName, parameters, body);
return convertTemplatesToLgFile(id, templates.toString(), templates);
}
export function removeTemplate(lgFile: LgFile, templateName: string, importResolver?: ImportResolverDelegate): LgFile {
const { id } = lgFile;
const resource = getLgResource(lgFile, importResolver);
const templates = resource.deleteTemplate(templateName);
return convertTemplatesToLgFile(id, templates.toString(), templates);
}
export function removeTemplates(
lgFile: LgFile,
templateNames: string[],
importResolver?: ImportResolverDelegate
): LgFile {
const { id } = lgFile;
let resource = getLgResource(lgFile, importResolver);
const normalizedLgTemplates = templateNames
.map((x) => {
const lgTemplateRef = LgTemplateRef.parse(x);
return lgTemplateRef ? lgTemplateRef.name : x;
})
.filter((x) => !!x);
const generatedLgTemplateNames = getGeneratedLgTemplateNames(lgFile, normalizedLgTemplates);
[...normalizedLgTemplates, ...generatedLgTemplateNames].forEach((templateName) => {
resource = resource.deleteTemplate(templateName);
});
return convertTemplatesToLgFile(id, resource.toString(), resource);
}
/**
* This util function returns the names of all auto generated templates associated with the templates being removed.
* @param file Lg file that contains the templates.
* @param toBeRemovedLgTemplateNames Names of Lg templates that are being removed.
*/
const getGeneratedLgTemplateNames = (file: LgFile, toBeRemovedLgTemplateNames: string[]) => {
const generatedLgTemplateNames: string[] = [];
const lgTemplates = file.templates.filter((t) => toBeRemovedLgTemplateNames.includes(t.name) && !!t.properties);
for (const lgTemplate of lgTemplates) {
// Auto-generated templates in structured responses have the following pattern
// [name of the parent template]_text OR [name of the parent template]_speak OR [name of the parent template]_attachment_[random string]
const pattern = `${lgTemplate.name}_((text|speak)|(attachment_.+))$`;
// eslint-disable-next-line security/detect-non-literal-regexp
const regex = new RegExp(`^${pattern}`);
const generatedLgTemplates = file.templates.map((t) => t.name).filter((name) => regex.test(name));
generatedLgTemplateNames.push(...generatedLgTemplates);
}
return generatedLgTemplateNames;
};
export function textFromTemplate(template: LgTemplate): string {
const { name, parameters = [], body } = template;
const textBuilder: string[] = [];
if (name && body !== null && body !== undefined) {
textBuilder.push(`# ${name.trim()}`);
if (parameters.length) {