Add in folder and in file logic
Improve reusability Add in folder Add in file restructure metadata file
This commit is contained in:
Родитель
f81dfeb663
Коммит
c0502d2813
|
@ -51,6 +51,9 @@ $ sgp -h
|
|||
}, console.log);
|
||||
```
|
||||
|
||||
### Module
|
||||
|
||||
Add CLI parameters to build package.xml for only certain types
|
||||
|
||||
## Built With
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
// TODO improve parameter to concentrate on create only certaine type
|
||||
|
||||
const program = require('commander');
|
||||
const orchestrator = require('../index.js');
|
||||
|
@ -14,5 +17,5 @@ program
|
|||
|
||||
orchestrator(program, console.log)
|
||||
.catch(function(err){
|
||||
console.log(err);
|
||||
throw err;
|
||||
});
|
3
index.js
3
index.js
|
@ -25,7 +25,8 @@ module.exports = (config,logger) => {
|
|||
const xml = xmlbuilder.create('Package')
|
||||
.att('xmlns', 'http://soap.sforce.com/2006/04/metadata')
|
||||
.dec('1.0', 'UTF-8');
|
||||
result.forEach(elem => {if(!!elem) xml.importDocument(elem)});
|
||||
|
||||
[].concat(...result).filter(elem => !!elem).forEach(elem => xml.importDocument(elem));
|
||||
xml.ele('version')
|
||||
.t(config.apiVersion);
|
||||
const xmlContent = xml.end({ pretty: true, indent: ' ', newline: '\n' });
|
||||
|
|
|
@ -1,14 +1,21 @@
|
|||
'use strict';
|
||||
const CustomLabels = require('../strategies/type-strategies/customlabel-type-strategy');
|
||||
const CustomLabel = require('../strategies/type-strategies/customlabel-type-strategy');
|
||||
const SubDef = require('../strategies/type-strategies/subdefinition-type-strategy');
|
||||
const Standard = require('../strategies/type-strategies/standard-type-strategy');
|
||||
const InFolder = require('../strategies/type-strategies/infolder-type-strategy');
|
||||
const metadata = require('../utils/metadata');
|
||||
|
||||
// TODO CustomObject
|
||||
// TODO Workflow
|
||||
// TODO email template and report dashboard and Document
|
||||
|
||||
const classes = {
|
||||
'CustomLabels' : CustomLabels
|
||||
'CustomLabels' : CustomLabel,
|
||||
'Workflow' : SubDef,
|
||||
'CustomObject' : SubDef,
|
||||
'EmailTemplate' : InFolder,
|
||||
'Document' : InFolder,
|
||||
'Report' : InFolder,
|
||||
'Dashboard' : InFolder
|
||||
};
|
||||
|
||||
module.exports = class StandardStrategy {
|
||||
|
|
|
@ -17,21 +17,23 @@ module.exports = class CustomLabelStrategy extends AbstractTypeStrategy {
|
|||
Promise.all(
|
||||
this.child.children
|
||||
.sort((a,b) => a.name.localeCompare(b.name))
|
||||
.map( aCustomLabelNode => readFileAsync(aCustomLabelNode.path,'utf8').then(xml2jsAsync))
|
||||
.map( aNode => readFileAsync(aNode,'utf8').then(xml2jsAsync))
|
||||
).then(result => {
|
||||
let isEmpty = true;
|
||||
const types = []
|
||||
const type = xmlbuilder.create('types');
|
||||
result.forEach( customLabelFile => {
|
||||
const customLabelDefinitions = customLabelFile.CustomLabels.labels
|
||||
const definitions = customLabelFile.content.CustomLabels.labels
|
||||
.sort((a,b) => a.fullName[0].localeCompare(b.fullName[0]));
|
||||
isEmpty &= customLabelDefinitions.length == 0;
|
||||
customLabelDefinitions.forEach(customLabelDefinition => {
|
||||
isEmpty &= definitions.length == 0;
|
||||
definitions.forEach(aDefinition => {
|
||||
type.ele('members')
|
||||
.t(customLabelDefinition.fullName[0]);
|
||||
.t(aDefinition.fullName[0]);
|
||||
})
|
||||
})
|
||||
type.ele('name').t(metadata[this.child.name].children[metadata[this.child.name].xmlName]);
|
||||
resolve(isEmpty ? undefined : type);
|
||||
types.push(type)
|
||||
resolve(isEmpty ? undefined : types);
|
||||
}).catch(reject);
|
||||
});
|
||||
return promise;
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
const metadata = require('../../utils/metadata');
|
||||
const xmlbuilder = require('xmlbuilder');
|
||||
|
||||
module.exports = class StandardStrategy {
|
||||
constructor(child) {
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
build(){
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const children = this.child.children.filter(elem => !elem.name.startsWith('.') && !elem.name.endsWith('-meta.xml'))
|
||||
if(children.length == 0) {
|
||||
resolve();
|
||||
}
|
||||
const types = []
|
||||
const type = xmlbuilder.create('types');
|
||||
children.sort((a,b) => a.name.localeCompare(b.name))
|
||||
.forEach(subChild => {
|
||||
type.ele('members')
|
||||
.t(subChild.name.replace(/\.[^/.]+$/,''));
|
||||
subChild.children && subChild.children.filter(elem => elem.extension && elem.extension != '.xml' && !elem.name.startsWith('.')).sort().forEach(subsubChild => {
|
||||
type.ele('members')
|
||||
.t(subChild.name+'/'+subsubChild.name.replace(/\.[^/.]+$/,''));
|
||||
})
|
||||
})
|
||||
type.ele('name').t(metadata[this.child.name].xmlName);
|
||||
types.push(type)
|
||||
resolve(types)
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
};
|
|
@ -12,6 +12,7 @@ module.exports = class StandardStrategy {
|
|||
if(children.length == 0) {
|
||||
resolve();
|
||||
}
|
||||
const types = []
|
||||
const type = xmlbuilder.create('types');
|
||||
children.sort((a,b) => a.name.localeCompare(b.name))
|
||||
.forEach(subChild => {
|
||||
|
@ -19,7 +20,8 @@ module.exports = class StandardStrategy {
|
|||
.t(subChild.name.replace(/\.[^/.]+$/,''));
|
||||
})
|
||||
type.ele('name').t(metadata[this.child.name].xmlName);
|
||||
resolve(type)
|
||||
types.push(type)
|
||||
resolve(types)
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
const metadata = require('../../utils/metadata');
|
||||
const xmlbuilder = require('xmlbuilder');
|
||||
const xml2jsAsync = require('../../utils/async-xml-parser');
|
||||
const readFileAsync = require('../../utils/async-read-file')
|
||||
const AbstractTypeStrategy = require('./standard-type-strategy');
|
||||
|
||||
module.exports = class SubDefinitionStrategy extends AbstractTypeStrategy {
|
||||
constructor(child) {
|
||||
super(child);
|
||||
}
|
||||
|
||||
build(){
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
if(this.child.children.length == 0) {
|
||||
resolve();
|
||||
}
|
||||
Promise.all(
|
||||
this.child.children
|
||||
.sort((a,b) => a.name.localeCompare(b.name))
|
||||
.map( aNode => readFileAsync(aNode,'utf8').then(xml2jsAsync))
|
||||
).then(result => {
|
||||
const struct = {}
|
||||
struct[metadata[this.child.name].xmlName] = [];
|
||||
result.forEach( aFile => {
|
||||
struct[metadata[this.child.name].xmlName].push(aFile.name.replace(/\.[^/.]+$/,''));
|
||||
const objectName = Object.keys(aFile.content)[0];
|
||||
for(let childDef in aFile.content[objectName]) if(metadata[this.child.name].children.hasOwnProperty(childDef)) {
|
||||
struct[metadata[this.child.name].children[childDef].typeName] = struct[metadata[this.child.name].children[childDef].typeName] || [];
|
||||
aFile.content[objectName][childDef].forEach(elem => struct[metadata[this.child.name].children[childDef].typeName].push(aFile.name.replace(/\.[^/.]+$/,'') + '.' + elem[metadata[this.child.name].children[childDef].name][0]));
|
||||
}
|
||||
})
|
||||
|
||||
const types = []
|
||||
Object.keys(struct).sort().forEach(aStruc => {
|
||||
const type = xmlbuilder.create('types');
|
||||
struct[aStruc].sort().forEach(elem => {
|
||||
type.ele('members')
|
||||
.t(elem);
|
||||
})
|
||||
type.ele('name').t(aStruc);
|
||||
types.push(type);
|
||||
})
|
||||
|
||||
resolve(types.length == 0 ? undefined : types);
|
||||
}).catch(reject);
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
};
|
|
@ -1,10 +1,11 @@
|
|||
const fs = require('fs');
|
||||
|
||||
const readFileAsync = (path) => {
|
||||
const readFileAsync = (file) => {
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
fs.readFile(path, (err, data) => {
|
||||
fs.readFile(file.path, (err, data) => {
|
||||
if (err) reject(err);
|
||||
resolve(data);
|
||||
file.content = data;
|
||||
resolve(file);
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
const xml2js = require('xml2js');
|
||||
|
||||
const parseStringAsync = (fileContent) => {
|
||||
const parseStringAsync = (file) => {
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const parser = new xml2js.Parser();
|
||||
parser.parseString(fileContent, (err, result) => {
|
||||
parser.parseString(file.content, (err, result) => {
|
||||
if (err) reject(err);
|
||||
resolve(result);
|
||||
file.content = result;
|
||||
resolve(file);
|
||||
});
|
||||
});
|
||||
return promise;
|
||||
|
|
|
@ -44,18 +44,17 @@ module.exports = {
|
|||
"objects":{
|
||||
"xmlName":"CustomObject",
|
||||
"children":{
|
||||
"actionOverrides":"ActionOverride",
|
||||
"fields":"CustomField",
|
||||
"businessProcesses":"BusinessProcess",
|
||||
"recordTypes":"RecordType",
|
||||
"webLinks":"WebLink",
|
||||
"validationRules":"ValidationRule",
|
||||
"namedFilters":"NamedFilter",
|
||||
"sharingReasons":"SharingReason",
|
||||
"listViews":"ListView",
|
||||
"fieldSets":"FieldSet",
|
||||
"sharingRecalculations":"SharingRecalculation",
|
||||
"compactLayouts":"CompactLayout"
|
||||
"actionOverrides":{"typeName":"ActionOverride","name":"actionName"},
|
||||
"fields":{"typeName":"CustomField","name":"fullName"},
|
||||
"businessProcesses":{"typeName":"BusinessProcess","name":"fullName"},
|
||||
"recordTypes":{"typeName":"RecordType","name":"fullName"},
|
||||
"webLinks":{"typeName":"WebLink","name":"fullName"},
|
||||
"validationRules":{"typeName":"ValidationRule","name":"fullName"},
|
||||
"namedFilters":{"typeName":"NamedFilter","name":"fullName"},
|
||||
"sharingReasons":{"typeName":"SharingReason","name":"fullName"},
|
||||
"listViews":{"typeName":"ListView","name":"fullName"},
|
||||
"fieldSets":{"typeName":"FieldSet","name":"fullName"},
|
||||
"compactLayouts":{"typeName":"WorkflowAlert","name":"fullName"}
|
||||
}
|
||||
},
|
||||
"reportTypes":{
|
||||
|
@ -151,14 +150,14 @@ module.exports = {
|
|||
"workflows":{
|
||||
"xmlName":"Workflow",
|
||||
"children":{
|
||||
"alerts":"WorkflowAlert",
|
||||
"tasks":"WorkflowTask",
|
||||
"outboundMessages":"WorkflowOutboundMessage",
|
||||
"fieldUpdates":"WorkflowFieldUpdate",
|
||||
"rules":"WorkflowRule",
|
||||
"emailRecipients":"WorkflowEmailRecipient",
|
||||
"timeTriggers":"WorkflowTimeTrigger",
|
||||
"actionReferences":"WorkflowActionReference"
|
||||
"alerts":{"typeName":"WorkflowAlert","name":"fullName"},
|
||||
"tasks":{"typeName" : "WorkflowTask", "name" : "fullName"},
|
||||
"outboundMessages":{"typeName" : "WorkflowOutboundMessage","name" : "fullName"},
|
||||
"fieldUpdates":{"typeName" : "WorkflowFieldUpdate", "name" : "fullName"},
|
||||
"rules":{"typeName" : "WorkflowRule", "name" : "fullName"},
|
||||
"emailRecipients":{"typeName" : "WorkflowEmailRecipient", "name" : "fullName"},
|
||||
"timeTriggers":{"typeName" : "WorkflowTimeTrigger", "name" : "fullName"},
|
||||
"actionReferences":{"typeName" : "WorkflowActionReference", "name" : "fullName"}
|
||||
}
|
||||
},
|
||||
"assignmentRules":{
|
||||
|
|
Загрузка…
Ссылка в новой задаче