Skip to content

Commit de854b6

Browse files
committed
chore: add v1 docs section
1 parent 1191b3a commit de854b6

19 files changed

+2201
-1
lines changed
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
layout: default
3+
category: document
4+
title: Document
5+
subtitle: JSforce library document with brief usage examples of each API
6+
sidebar: menu
7+
scripts:
8+
- '/js/document.js'
9+
---
10+
11+
<%- @partial('document-v1/connection') %>
12+
13+
<%- @partial('document-v1/oauth2') %>
14+
15+
<%- @partial('document-v1/query') %>
16+
17+
<%- @partial('document-v1/search') %>
18+
19+
<%- @partial('document-v1/crud') %>
20+
21+
<%- @partial('document-v1/describe') %>
22+
23+
<%- @partial('document-v1/identity') %>
24+
25+
<%- @partial('document-v1/history') %>
26+
27+
<%- @partial('document-v1/limit') %>
28+
29+
<%- @partial('document-v1/analytics') %>
30+
31+
<%- @partial('document-v1/apex') %>
32+
33+
<%- @partial('document-v1/bulk') %>
34+
35+
<%- @partial('document-v1/chatter') %>
36+
37+
<%- @partial('document-v1/metadata') %>
38+
39+
<%- @partial('document-v1/streaming') %>
40+
41+
<%- @partial('document-v1/tooling') %>
42+
43+
<%- @partial('document-v1/advanced') %>

src/documents/document/index.html.eco

+8-1
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22
layout: default
33
category: document
44
title: Document
5-
subtitle: JSforce library document with brief usage examples of each API
5+
subtitle: JSforce library document with brief usage examples of each API.
66
sidebar: menu
77
scripts:
88
- '/js/document.js'
99
---
1010

11+
<b>NOTE:</b>
12+
13+
These docs are for jsforce v3.
14+
<a href="/document-v1/">Looking for v1 docs?</a>
15+
1116
<%- @partial('document/connection') %>
1217

1318
<%- @partial('document/oauth2') %>
@@ -43,3 +48,5 @@ scripts:
4348
<%- @partial('document/tooling') %>
4449

4550
<%- @partial('document/advanced') %>
51+
52+
<h3><a href="https://github.com/jsforce/jsforce.github.io">Edit this page</a></h3>
+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
---
2+
---
3+
4+
## Advanced Topics
5+
6+
### Record Stream Pipeline
7+
8+
Record stream is a stream system which regards records in its stream, similar to Node.js's standard readable/writable streams.
9+
10+
Query object - usually returned by `Connection#query(soql)` / `SObject#find(conditions, fields)` methods -
11+
is considered as `InputRecordStream` which emits event `record` when received record from server.
12+
13+
Batch object - usually returned by `Bulk-Job#createBatch()` / `Bulk#load(sobjectType, operation, input)` / `SObject#bulkload(operation, input)` methods -
14+
is considered as `OutputRecordStream` and have `send()` and `end()` method to accept incoming record.
15+
16+
You can use `InputRecordStream#pipe(outputRecordStream)` to pipe record stream.
17+
18+
RecordStream can be converted to usual Node.js's stream object by calling `RecordStream#stream()` method.
19+
20+
By default (and only currently) records are serialized to CSV string.
21+
22+
23+
#### Piping Query Record Stream to Batch Record Stream
24+
25+
The idea of record stream pipeline is the base of bulk operation for queried record.
26+
For example, the same process of `Query#destroy()` can be expressed as following:
27+
28+
29+
```javascript
30+
//
31+
// This is much more complex version of Query#destroy().
32+
//
33+
var Account = conn.sobject('Account');
34+
Account.find({ CreatedDate: { $lt: jsforce.Date.LAST_YEAR }})
35+
.pipe(Account.deleteBulk())
36+
.on('response', function(rets){
37+
// ...
38+
})
39+
.on('error', function(err) {
40+
// ...
41+
});
42+
```
43+
44+
And `Query#update(mapping)` can be expressed as following:
45+
46+
```javascript
47+
//
48+
// This is much more complex version of Query#update().
49+
//
50+
var Opp = conn.sobject('Opportunity');
51+
Opp.find({ "Account.Id" : accId },
52+
{ Id: 1, Name: 1, "Account.Name": 1 })
53+
.pipe(jsforce.RecordStream.map(function(r) {
54+
return { Id: r.Id,
55+
Name: r.Account.Name + ' - ' + r.Name };
56+
}))
57+
.pipe(Opp.updateBulk())
58+
.on('response', function(rets) {
59+
// ...
60+
})
61+
.on('error', function(err) {
62+
// ...
63+
});
64+
```
65+
66+
Following is an example using `Query#stream()` (inherited `RecordStream#stream()`) to convert record stream to Node.js stream,
67+
in order to export all queried records to CSV file.
68+
69+
```javascript
70+
var csvFileOut = require('fs').createWriteStream('path/to/Account.csv');
71+
conn.query("SELECT Id, Name, Type, BillingState, BillingCity, BillingStreet FROM Account")
72+
.stream() // Convert to Node.js's usual readable stream.
73+
.pipe(csvFileOut);
74+
```
75+
76+
#### Record Stream Filtering / Mapping
77+
78+
You can also filter / map queried records to output record stream.
79+
Static functions like `InputRecordStream#map(mappingFn)` and `InputRecordStream#filter(filterFn)` create a record stream
80+
which accepts records from upstream and pass to downstream, applying given filtering / mapping function.
81+
82+
```javascript
83+
//
84+
// Write down Contact records to CSV, with header name converted.
85+
//
86+
conn.sobject('Contact')
87+
.find({}, { Id: 1, Name: 1 })
88+
.map(function(r) {
89+
return { ID: r.Id, FULL_NAME: r.Name };
90+
})
91+
.stream().pipe(fs.createWriteStream("Contact.csv"));
92+
//
93+
// Write down Lead records to CSV file,
94+
// eliminating duplicated entry with same email address.
95+
//
96+
var emails = {};
97+
conn.sobject('Lead')
98+
.find({}, { Id: 1, Name: 1, Company: 1, Email: 1 })
99+
.filter(function(r) {
100+
var dup = emails[r.Email];
101+
if (!dup) { emails[r.Email] = true; }
102+
return !dup;
103+
})
104+
.stream().pipe(fs.createWriteStream("Lead.csv"));
105+
```
106+
107+
Here is much lower level code to achieve the same result using `InputRecordStream#pipe()`.
108+
109+
110+
```javascript
111+
//
112+
// Write down Contact records to CSV, with header name converted.
113+
//
114+
conn.sobject('Contact')
115+
.find({}, { Id: 1, Name: 1 })
116+
.pipe(jsforce.RecordStream.map(function(r) {
117+
return { ID: r.Id, FULL_NAME: r.Name };
118+
}))
119+
.stream().pipe(fs.createWriteStream("Contact.csv"));
120+
//
121+
// Write down Lead records to CSV file,
122+
// eliminating duplicated entry with same email address.
123+
//
124+
var emails = {};
125+
conn.sobject('Lead')
126+
.find({}, { Id: 1, Name: 1, Company: 1, Email: 1 })
127+
.pipe(jsforce.RecordStream.filter(function(r) {
128+
var dup = emails[r.Email];
129+
if (!dup) { emails[r.Email] = true; }
130+
return !dup;
131+
}))
132+
.stream().pipe(fs.createWriteStream("Lead.csv"));
133+
```
134+
135+
#### Example: Data Migration
136+
137+
By using record stream pipeline, you can achieve data migration in a simple code.
138+
139+
```javascript
140+
//
141+
// Connection for org which migrating data from
142+
//
143+
var conn1 = new jsforce.Connection({
144+
// ...
145+
});
146+
//
147+
// Connection for org which migrating data to
148+
//
149+
var conn2 = new jsforce.Connection({
150+
// ...
151+
});
152+
//
153+
// Get query record stream from Connetin #1
154+
// and pipe it to batch record stream from connection #2
155+
//
156+
var query = conn1.query("SELECT Id, Name, Type, BillingState, BillingCity, BillingStreet FROM Account");
157+
var job = conn2.bulk.createJob("Account", "insert");
158+
var batch = job.createBatch();
159+
query.pipe(batch);
160+
batch.on('queue', function() {
161+
jobId = job.id;
162+
batchId = batch.id;
163+
//...
164+
})
165+
```
+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
---
2+
---
3+
4+
## Analytics API
5+
6+
By using Analytics API, you can get the output result from a report registered in Salesforce.
7+
8+
### Get Recently Used Reports
9+
10+
`Analytics#reports()` lists recently accessed reports.
11+
12+
```javascript
13+
/* @interactive */
14+
// get recent reports
15+
conn.analytics.reports(function(err, reports) {
16+
if (err) { return console.error(err); }
17+
console.log("reports length: "+reports.length);
18+
for (var i=0; i < reports.length; i++) {
19+
console.log(reports[i].id);
20+
console.log(reports[i].name);
21+
}
22+
// ...
23+
});
24+
```
25+
26+
### Describe Report Metadata
27+
28+
`Analytics#report(reportId)` gives a reference to the report object specified in `reportId`.
29+
By calling `Analytics-Report#describe()`, you can get the report metadata defined in Salesforce without executing the report.
30+
31+
You should check [Analytics REST API Guide](http://www.salesforce.com/us/developer/docs/api_analytics/index.htm) to understand the structure of returned report metadata.
32+
33+
```javascript
34+
/* @interactive */
35+
var reportId = '00O10000000pUw2EAE';
36+
conn.analytics.report(reportId).describe(function(err, meta) {
37+
if (err) { return console.error(err); }
38+
console.log(meta.reportMetadata);
39+
console.log(meta.reportTypeMetadata);
40+
console.log(meta.reportExtendedMetadata);
41+
});
42+
```
43+
44+
### Execute Report
45+
46+
#### Execute Synchronously
47+
48+
By calling `Analytics-Report#execute(options)`, the report is exected in Salesforce, and returns executed result synchronously.
49+
Please refer to Analytics API document about the format of retruning result.
50+
51+
```javascript
52+
/* @interactive */
53+
// get report reference
54+
var reportId = '00O10000000pUw2EAE';
55+
var report = conn.analytics.report(reportId);
56+
57+
// execute report synchronously
58+
report.execute(function(err, result) {
59+
if (err) { return console.error(err); }
60+
console.log(result.reportMetadata);
61+
console.log(result.factMap);
62+
console.log(result.factMap["T!T"]);
63+
console.log(result.factMap["T!T"].aggregates);
64+
// ...
65+
});
66+
```
67+
68+
#### Include Detail Rows in Execution
69+
70+
Setting `details` to true in `options`, it returns execution result with detail rows.
71+
72+
```javascript
73+
/* @interactive */
74+
// execute report synchronously with details option,
75+
// to get detail rows in execution result.
76+
var reportId = '00O10000000pUw2EAE';
77+
var report = conn.analytics.report(reportId);
78+
report.execute({ details: true }, function(err, result) {
79+
if (err) { return console.error(err); }
80+
console.log(result.reportMetadata);
81+
console.log(result.factMap);
82+
console.log(result.factMap["T!T"]);
83+
console.log(result.factMap["T!T"].aggregates);
84+
console.log(result.factMap["T!T"].rows); // <= detail rows in array
85+
// ...
86+
});
87+
```
88+
89+
#### Override Report Metadata in Execution
90+
91+
You can override report behavior by putting `metadata` object in `options`.
92+
For example, following code shows how to update filtering conditions of a report on demand.
93+
94+
```javascript
95+
/* @interactive */
96+
// overriding report metadata
97+
var metadata = {
98+
reportMetadata : {
99+
reportFilters : [{
100+
column: 'COMPANY',
101+
operator: 'contains',
102+
value: ',Inc.'
103+
}]
104+
}
105+
};
106+
// execute report synchronously with overridden filters.
107+
var reportId = '00O10000000pUw2EAE';
108+
var report = conn.analytics.report(reportId);
109+
report.execute({ metadata : metadata }, function(err, result) {
110+
if (err) { return console.error(err); }
111+
console.log(result.reportMetadata);
112+
console.log(result.reportMetadata.reportFilters.length); // <= 1
113+
console.log(result.reportMetadata.reportFilters[0].column); // <= 'COMPANY'
114+
console.log(result.reportMetadata.reportFilters[0].operator); // <= 'contains'
115+
console.log(result.reportMetadata.reportFilters[0].value); // <= ',Inc.'
116+
// ...
117+
});
118+
```
119+
120+
#### Execute Asynchronously
121+
122+
`Analytics-Report#executeAsync(options)` executes the report asynchronously in Salesforce,
123+
registering an instance to the report to lookup the executed result in future.
124+
125+
```javascript
126+
/* @interactive */
127+
var instanceId;
128+
129+
// execute report asynchronously
130+
var reportId = '00O10000000pUw2EAE';
131+
var report = conn.analytics.report(reportId);
132+
report.executeAsync({ details: true }, function(err, instance) {
133+
if (err) { return console.error(err); }
134+
console.log(instance.id); // <= registered report instance id
135+
instanceId = instance.id;
136+
// ...
137+
});
138+
```
139+
140+
Afterward use `Analytics-Report#instance(instanceId)`
141+
and call `Analytics-ReportInstance#retrieve()` to get the executed result.
142+
143+
```javascript
144+
/* @interactive */
145+
// retrieve asynchronously executed result afterward.
146+
report.instance(instanceId).retrieve(function(err, result) {
147+
if (err) { return console.error(err); }
148+
console.log(result.reportMetadata);
149+
console.log(result.factMap);
150+
console.log(result.factMap["T!T"]);
151+
console.log(result.factMap["T!T"].aggregates);
152+
console.log(result.factMap["T!T"].rows);
153+
// ...
154+
});
155+
```
156+

0 commit comments

Comments
 (0)