-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathcli.js
215 lines (203 loc) · 8.36 KB
/
cli.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
var fs = require('fs');
var path = require('path');
var commander = require('commander');
var jsforce = require('jsforce');
var tools = require('./index');
var pkg = require('../package.json');
var Promise = jsforce.Promise;
function acceptConnectionOptions(program) {
program.option('-u, --username [username]', 'Salesforce username')
.option('-p, --password [password]', 'Salesforce password (and security token, if available)')
.option('-c, --connection [connection]', 'Connection name stored in connection registry')
.option('-l, --loginUrl [loginUrl]', 'Salesforce login url')
.option('--sandbox', 'Login to Salesforce sandbox');
}
function acceptCommonOptions(program) {
program.option('--verbose', 'Output execution detail log')
.version(pkg.version);
}
function readOptions(program) {
var options = {};
"username,password,connection,loginUrl,pollInterval,pollTimeout".split(',').forEach(function(prop) {
if (typeof program[prop] !== 'undefined') { options[prop] = program[prop]; }
});
if (program.sandbox) {
options.loginUrl = 'https://test.salesforce.com';
}
options.logger = console;
return options;
}
function readDeployOptions(program) {
var options = readOptions(program);
"testLevel,runTests,ignoreWarnings,rollbackOnError,checkOnly".split(',').forEach(function(prop) {
if (typeof program[prop] !== 'undefined') { options[prop] = program[prop]; }
});
if (program.dryRun) {
options.checkOnly = true;
}
return options;
}
function readRetrieveOptions(program) {
var options = readOptions(program);
"apiVersion".split(',').forEach(function(prop) {
if (typeof program[prop] !== 'undefined') { options[prop] = program[prop]; }
});
return options;
}
function parseList(a) {
return a.split(/\s*,\s*/);
}
function showInvalidOptionError(message, program) {
console.error('');
console.error(' Error: Invalid option.' + (message || ''));
program.help();
process.exit(1);
}
/**
*
*/
function deploy() {
var program = new commander.Command();
acceptConnectionOptions(program);
program.option('-D, --directory [directory]', 'Local directory path of the package to deploy')
.option('-Z, --zipFile [zipFile]', 'Input file path of ZIP archive of metadata files to deploy')
.option('--pid [pid]', 'Process ID of previous deployment to check status')
.option('--dry-run', 'Dry run. Same as --checkOnly')
.option('--checkOnly', 'Whether Apex classes and triggers are saved to the organization as part of the deployment')
.option('--testLevel [testLevel]', 'Specifies which tests are run as part of a deployment (NoTestRun/RunSpecifiedTests/RunLocalTests/RunAllTestsInOrg)')
.option('--runTests [runTests]', 'A list of Apex tests to run during deployment (commma separated)', parseList)
.option('--ignoreWarnings', 'Indicates whether a warning should allow a deployment to complete successfully (true) or not (false).')
.option('--rollbackOnError', 'Indicates whether any failure causes a complete rollback (true) or not (false)')
.option('--pollTimeout [pollTimeout]', 'Polling timeout in millisec (default is 60000ms)', parseInt)
.option('--pollInterval [pollInterval]', 'Polling interval in millisec (default is 5000ms)', parseInt)
acceptCommonOptions(program);
program.parse(process.argv);
var options = readDeployOptions(program);
if (!program.zipFile && !program.directory && !program.pid) {
return showInvalidOptionError(
'Please set --directory or --zipFile option to specify deploying package content, or set --pid for previous deployment process ID.',
program
);
}
(
program.zipFile ? tools.deployFromZipStream(fs.createReadStream(program.zipFile), options) :
program.directory ? tools.deployFromDirectory(program.directory, options) :
program.pid ? tools.checkDeployStatus(program.pid, options) :
Promise.reject(new Error('Invalid Options'))
)
.then(function(res) {
console.log('');
tools.reportDeployResult(res, console, program.verbose);
if (!res.success) {
process.exit(1);
} else {
process.exit(0);
}
})
.catch(function(err) {
console.error(err.message);
process.exit(1);
});
}
/**
*
*/
function retrieve() {
var program = new commander.Command();
acceptConnectionOptions(program);
program.option('-D, --directory [directory]',
'Directory path to extract the retrieved metadata files. ' +
'Should be a list (comma-separated) if there are multiple entries in packageNames',
parseList)
.option('-Z, --zipFile [zipFile]', 'Output file path of ZIP archive of retrieved metadata')
.option('-P, --packageXML [packageXML]', 'A package.xml file path to specify the retrieving metadata contents')
.option('--pid [pid]', 'Process ID of previous retrieve request')
.option('--apiVersion [apiVersion]', 'API version of retrieving package')
.option('--packageNames [packageNames]', 'List of package names to retrieve (comma separated)', parseList)
.option('--memberTypes [memberTypes]', 'Metadata types and its members. The format is like following: "ApexClass:Class1,Class2;ApexPage:Page1,Page2;ApexTrigger:*"')
.option('--pollTimeout [pollTimeout]', 'Polling timeout in millisec (default is 60000ms)', parseInt)
.option('--pollInterval [pollInterval]', 'Polling interval in millisec (default is 5000ms)', parseInt)
acceptCommonOptions(program);
program.parse(process.argv);
var options = readRetrieveOptions(program);
if (!program.directory && !program.zipFile) {
return showInvalidOptionError(
'Please set --directory or --zipFile option to specify the destination of retrieved metadata package.',
program
);
}
if (program.packageNames && program.directory && program.packageNames.length !== program.directory.length) {
return showInvalidOptionError(
'Please set output directory paths in --directory option, corresponding to entiries in packageNames option.',
program
);
}
if (!program.pid && !program.memberTypes && !program.packageNames && !program.packageXML &&
(!program.directory || program.directory.length !== 1)) {
return showInvalidOptionError(
'Please set --packageNames or --memberTypes in options, or speclify package.xml file path in --packageXML option',
program
);
}
(
program.pid ? tools.checkRetrieveStatus(program.pid, options) :
program.memberTypes ? tools.retrieveByTypes(program.memberTypes, options) :
program.packageNames ? tools.retrieveByPackageNames(program.packageNames, options) :
program.packageXML ? tools.retrieveByPackageXML(program.packageXML, options) :
program.directory && program.directory.length === 1 ? tools.retrieveByPackageXML(path.join(program.directory[0], 'package.xml'), options) :
Promise.reject(new Error('Invalid option'))
)
.then(function(res) {
console.log('');
tools.reportRetrieveResult(res, console, program.verbose);
if (res.success !== 'true') {
console.log('');
console.log('No output files generated.');
return false;
} else if (program.zipFile) {
fs.writeFileSync(program.zipFile, new Buffer(res.zipFile, 'base64'));
console.log('');
console.log('Retrieved metadata files are saved in a ZIP archive: ' + program.zipFile);
return true;
} else if (program.directory) {
var dirMapping = {};
if (program.packageNames) {
for (var i=0; i<program.packageNames.length; i++) {
dirMapping[program.packageNames[i]] = program.directory[i];
}
} else {
dirMapping['*'] = program.directory[0];
}
return tools.extractZipContents(res.zipFile, dirMapping, console, program.verbose)
.then(function() {
console.log('');
console.log('Retrieved metadata files are saved under the directory: ');
program.directory.forEach(function(dir) { console.log(' ' + dir); });
return true;
});
} else {
return false;
}
})
.then(function(success) {
console.log('');
if (!success) {
process.exit(1);
} else {
process.exit(0);
}
})
.catch(function(err) {
console.log('');
console.error(' Error: '+err.message);
console.log('');
process.exit(1);
});
}
/**
*
*/
module.exports = {
deploy: deploy,
retrieve: retrieve
};