JSforce使用技巧

本文有如下几个大主题:

1) 利用JSforce获取和更新Salesforce中的Permission
2) 利用JSforce新建字段
3) 利用JSforce获取Lightning Components

jsforce官方库如下:

https://jsforce.github.io/document/#bulk-api)

如何利用Jsforce获取Salesforce中的Permission

Permission 在Salesforce中有如下metadata:

  • fullName
  • applicationVisibilities
  • classAccesses
  • fieldPermissions
  • label
  • objectPermissions
  • pageAccesses
  • recordTypeVisibilities
  • tabSettings

更新permission

首先进行登入

1
2
3
4
5
var jsforce = require('jsforce'); 
var conn = new jsforce.Connection({
loginUrl: 'https://login.salesforce.com',
version: '36.0'
});

下面演示如何更新一个’ApexControllerName’的apexClass的permission。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
conn.login('username', 'password', function(err, res) { 
if (err) {
return console.error(err);
}
var metadata = {
"fullName": "PermissionAPIName",
"label": "Permission Label",
"classAccesses": [{
"apexClass": "ApexControllerName",
"enabled": "true"
}]
};
conn.metadata.update('PermissionSet', metadata, function(err, results) {
if (err) { console.error(err); }
console.log(results);
});
});

同时,你所使用的user必须是 ModifyAllData permission,否则就会有如下报错

1
2
3
{ [sf:INSUFFICIENT_ACCESS: INSUFFICIENT_ACCESS: use of the Metadata API requires a user with the ModifyAllData permission] 
name: 'sf:INSUFFICIENT_ACCESS',
errorCode: 'sf:INSUFFICIENT_ACCESS' }

获取Permission信息

1
2
3
4
5
6
 conn.query("select id,Name,Label,NamespacePrefix,IsOwnedByProfile,Description from PermissionSet where IsOwnedByProfile =false and NamespacePrefix=null ", function(err, result) {
if (err) { return console.error(err); }
for (var i = 0; i < result.records.length; i++) {
console.log("permission name : " + result.records[i].Name);
}
});

利用JSforce新建字段

如下例子在Account Object下新建一个Auto Number Fields。其中metadata 可以试一个List,也就是说,可以一次性新建多个不同类型的字段。由于这里没有涉及permission, 所以新建的字段是没有permission的。需要再次添加。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
conn.login('username', 'password', function(err, res) {
if (err) {
return console.error(err);
}
var metadata = [{
fullName: 'Account.AutoNumberFields__c',
label: 'Auto Nums',
type: 'Text',
length: 100

}];
conn.metadata.create('CustomField', metadata, function(err, results) {
if (err) {
console.error(err);
}
console.log(results);
for (var i = 0; i < results.length; i++) {
var result = results[i];
console.log('success ? : ' + result.success);
console.log('fullName : ' + result.fullName);
}
});
});

至于其他字段,文本区TextArea如下:

1
2
3
4
5
6
{
fullName: 'Object__c.TextArea__c',
label: '文本区',
required: false,
type: 'TextArea',
}

复选框Checkbox如下:

1
2
3
4
5
6
7
{
fullName: 'Object__c.Checkbox__c',
label: '复选框',
type: 'Checkbox',
defaultValue: false

}

数字 Number,如下:

1
2
3
4
5
6
7
8
{
fullName: 'Object__c.Number__c',
label: '数字',
required: false,
type: 'Number',
precision: 18,
scale: 2
}

Picklist 如下:

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
{
fullName: 'Object__c.Piklist__c',
label: '选题',
required: false,
type: 'Picklist',
picklist: {
picklistValues: [{
fullName: "Draft",
default: true
}, {
fullName: "Submitted",
default: false
}, {
fullName: "Final",
default: false
}, {
fullName: "Complete",
default: false
}, {
fullName: "Approved",
default: false
}, {
fullName: "Rejected",
default: false
}, {
fullName: "Closed",
default: false
}],
sorted: false
}
}

Date 如下:

1
2
3
4
5
6
{
fullName: 'Object__c.Date__c',
label: 'Date',
required: false,
type: 'Date'
}

MultiselectPicklist 如下:

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

{
fullName: 'Object__c.MultiselectPicklist__c',
label: '多选题',
required: false,
type: 'MultiselectPicklist',
visibleLines: 6,
picklist: {
picklistValues: [{
fullName: "水污染",
default: true
}, {
fullName: "大气污染",
default: false
}, {
fullName: "植被破坏",
default: false
}, {
fullName: "固体废弃物污染",
default: false
}, {
fullName: "污染",
default: false
}, {
fullName: "核污染",
default: false
}],
sorted: false
}
}

利用JSforce获取Lightning Components

几个重要SOQL收录如下:

1
2
3
4
5
SELECT Id,description,apiVersion FROM AuraDefinitionBundle 

select id, AuraDefinitionBundleId,Format,DefType,Source from AuraDefinition

SELECT Id,description,apiVersion,DeveloperName FROM AuraDefinitionBundle

可以利用如下function获得Lightning Components:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 function FetchLightningComp(inputSQL) {
conn.query(inputSQL, function(err, result) {
if (err) {
return console.error(err);
}
for (var i = 0; i < result.records.length; i++) {
console.log(result.records[i].DefType + '||' + result.records[i].AuraDefinitionBundle.DeveloperName);
if (result.records[i].Source != '(hidden)') {

//Create Folder
CraetingLightningComp(result.records[i]);
}
}
});
}

由于Lightning Components是由js,css一系列组成,所以需要每一个Components建立一个folder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//create lightning folder and file 
function CraetingLightningComp(InputObject) {
mkdirp(datetime + '/LightningComponent/' + InputObject.AuraDefinitionBundle.DeveloperName, function(err) {
if (err) {
console.error(err)
} else {
if (InputObject.Format === 'JS' || InputObject.Format == 'CSS') {
writefile(InputObject.DefType + '.' + InputObject.Format, 'LightningComponent/' + InputObject.AuraDefinitionBundle.DeveloperName, InputObject.Source);
} else {
writefileVF(InputObject.DefType + '.' + InputObject.Format, 'LightningComponent/' + InputObject.AuraDefinitionBundle.DeveloperName, InputObject.Source);
}
}
});
}

这里的writefile和writefileVF是新建一个文件,具体写法如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function writefile(InputName, MetaType, InputBody) {
var beautify = require('js-beautify').js_beautify,
fs = require('fs');
var InsertBody = beautify(InputBody, {
indent_size: 2
});
fs.writeFile(datetime + '/' + MetaType + '/' + InputName, InsertBody, function(err) {
if (err) {
return console.log(err);
}
});
}

function writefileVF(InputName, MetaType, InputBody) {
var fs = require('fs');
fs.writeFile(datetime + '/' + MetaType + '/' + InputName, InputBody, function(err) {
if (err) {
return console.log(err);
}
});
}

如果获得的Lightning Components得数量某一定的值,可能获取不到,这里分开不同的SQL获得对应的Lightning Components

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function FetchLightningResources(inputSQL) {
conn.query(inputSQL, function(err, result) {
if (err) {
return console.error(err);
}
console.log("fetched: " + result.records.length);
console.log(result);

if (result.totalSize > 0) {
for (var i = 0; i < result.totalSize; i = i + 200) {
console.log(inputSQL + ' offset ' + i);
FetchLightningComp(inputSQL + ' offset ' + i);
}
}
});
}

最后相对应的call function可以如下:

1
2

FetchLightningResources('select id, AuraDefinitionBundleId,AuraDefinitionBundle.DeveloperName,Format,DefType,Source from AuraDefinition');

参考文献