autoforce
Version:
Developer Automation tool for Github / Gitlab and Salesforce projects.
229 lines (225 loc) • 6.84 kB
JavaScript
import sf from "./connect.js";
import { default as templateGenerator } from "./template.js";
import { DICTIONARY_FOLDER, getModelFolders } from "./util.js";
let _templateEngine;
function getTemplateEngine() {
if (!_templateEngine) {
_templateEngine = templateGenerator(getModelFolders('templates/dictionary'), "md");
}
return _templateEngine;
}
import { sortByName, getNamesByExtension, verFecha, splitFilename } from "./util.js";
async function getMetadata(clases) {
try {
await sf.connect();
const classRecords = await sf.getClasses(clases);
return Array.isArray(classRecords) ? classRecords : [classRecords];
}
catch (e) {
console.error(e);
}
return [];
}
export function getClasses(files) {
const items = new Set();
for (const file of files) {
if (file.indexOf("/classes/") > 0) {
const { filename } = splitFilename(file);
items.add(filename.split(".")[0]);
}
}
return [...items.values()];
}
function classLink() {
const name = this.Name;
return `./diccionarios/classes/${name}`;
}
function classLinkGraph() {
const name = this.Name;
return `./diccionarios/classes/${name}`;
}
function linkToType() {
const dictionaryClasses = getNamesByExtension(DICTIONARY_FOLDER + "/classes", "md");
const fullType = this.replace("<", "~").replace(">", "~");
const types = fullType.split("~");
for (const t in types) {
if (dictionaryClasses.includes(t)) {
fullType.replace(t, `[{t}](./diccionarios/classes/{t})`);
}
}
return fullType;
}
function filterByPublic() {
return this.modifiers.includes("public") || this.modifiers.includes("global");
}
function scopeModifiers() {
const modifiers = [];
if (this.modifiers.includes("public") || this.modifiers.includes("global")) {
modifiers.push(`+`);
}
if (this.modifiers.includes("private")) {
modifiers.push(`-`);
}
if (this.modifiers.includes("protected")) {
modifiers.push(`#`);
}
return modifiers.join(" ");
}
function modifiers() {
const modifiers = [];
if (this.modifiers.includes("abstract")) {
modifiers.push(`*`);
}
if (this.modifiers.includes("override")) {
modifiers.push(`o`);
}
if (this.modifiers.includes("static") || this.modifiers.includes("final")) {
modifiers.push(`$`);
}
return modifiers.join(" ");
}
function classAttributes() {
const attributes = [];
// if (this.isValid === "true") {
// attributes.push(``);
// }
const systemTable = this.SymbolTable;
if (systemTable.tableDeclaration.modifiers.includes("static")) {
attributes.push(`$`);
}
if (systemTable.tableDeclaration.modifiers.includes("public") ||
systemTable.tableDeclaration.modifiers.includes("global")) {
attributes.push(`+`);
}
if (systemTable.tableDeclaration.modifiers.includes("private")) {
attributes.push(`-`);
}
if (systemTable.tableDeclaration.modifiers.includes("protected")) {
attributes.push(`#`);
}
if (systemTable.tableDeclaration.modifiers.includes("global")) {
attributes.push(`G`);
}
return attributes.join(" ");
}
function getInnerClasses(classes) {
let ret = [];
for (const clase of classes) {
if (clase.SymbolTable && clase.SymbolTable.innerClasses.length > 0) {
const innerClases = clase.SymbolTable.innerClasses.map((subclase) => {
subclase.namespace =
(clase.namespace ? clase.namespace + "." : "") + clase.Name;
return {
Name: subclase.Name,
type: "inner",
namespace: subclase.namespace,
SymbolTable: [subclase]
};
});
ret = ret.concat(innerClases);
const subInner = getInnerClasses(clase.SymbolTable.innerClasses);
ret = ret.concat(subInner);
}
}
return ret;
}
export async function executeClasses(items, filename, folder) {
const templateEngine = getTemplateEngine();
if (items.length === 0) {
return;
}
// Busca la metadata
let contexts = await getMetadata(items);
if (!contexts || contexts.length === 0) {
return;
}
// Arma el diccionario de cada Clase
templateEngine.read("class");
for (const context of contexts) {
templateEngine.render(context, {
helpers: {
verFecha,
modifiers,
linkToType,
classLinkGraph,
filterByPublic,
classAttributes,
scopeModifiers
}
});
templateEngine.save(context.Name, DICTIONARY_FOLDER + "/classes");
}
// Saca las innerClass y las pone como clases con namespace
const innerClasses = getInnerClasses(contexts);
const namespaces = {};
if (innerClasses.length > 0) {
templateEngine.read("class-inner");
for (const context of innerClasses) {
templateEngine.render(context, {
helpers: { verFecha, modifiers, linkToType }
});
templateEngine.save(context.Name, DICTIONARY_FOLDER + "/classes/" + context.namespace);
// arma un mapa de namespace con el array de sus innerclases
if (context.namespace) {
if (namespaces[context.namespace] === undefined) {
namespaces[context.namespace] = [context.Name];
}
else {
namespaces[context.namespace].push(context.Name);
}
}
}
contexts = contexts.concat(innerClasses);
}
// Arma el documento indice del grupo de clases
contexts.sort(sortByName);
templateEngine.read("classes");
const classContext = { classes: contexts, namespaces };
templateEngine.render(classContext, {
helpers: {
verFecha,
modifiers,
linkToType,
filterByPublic,
classLinkGraph,
classLink
}
});
templateEngine.save(filename, +"/" + folder);
}
const classModule = {
getItems: getClasses,
execute: executeClasses
};
export default classModule;
/**
* TODO
* innerClass
* annotations
* locations links
* complex types Map<Class, Class>
* relaciones composicion, etc
*/
/* annotations
@AuraEnabled
@TestSetup
@TestVisible
@IsTest
@Future
@Deprecated
@InvocableMethod
@InvocableVariable
@JsonAccess
@NamespaceAccessible
@ReadOnly
@RemoteAction
@SuppressWarnings
@ReadOnly
REST API
@RestResource(urlMapping='/nombremiapi')
@HttpDelete
@HttpGet
@HttpPatch
@HttpPost
@HttpPut
*/