@jsforce/jsforce-node 0.0.1 → 3.0.0-next.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +54 -0
- package/index.d.ts +4 -0
- package/index.js +1 -0
- package/lib/VERSION.d.ts +2 -0
- package/lib/VERSION.js +3 -0
- package/lib/api/analytics/types.d.ts +509 -0
- package/lib/api/analytics/types.js +2 -0
- package/lib/api/analytics.d.ts +163 -0
- package/lib/api/analytics.js +342 -0
- package/lib/api/apex.d.ts +44 -0
- package/lib/api/apex.js +86 -0
- package/lib/api/bulk.d.ts +444 -0
- package/lib/api/bulk.js +1372 -0
- package/lib/api/chatter.d.ts +133 -0
- package/lib/api/chatter.js +248 -0
- package/lib/api/metadata/schema.d.ts +16117 -0
- package/lib/api/metadata/schema.js +9094 -0
- package/lib/api/metadata.d.ts +189 -0
- package/lib/api/metadata.js +406 -0
- package/lib/api/soap/schema.d.ts +3167 -0
- package/lib/api/soap/schema.js +1787 -0
- package/lib/api/soap.d.ts +76 -0
- package/lib/api/soap.js +155 -0
- package/lib/api/streaming/extension.d.ts +94 -0
- package/lib/api/streaming/extension.js +151 -0
- package/lib/api/streaming.d.ts +160 -0
- package/lib/api/streaming.js +252 -0
- package/lib/api/tooling.d.ts +284 -0
- package/lib/api/tooling.js +202 -0
- package/lib/api/wsdl/wsdl2schema.d.ts +1 -0
- package/lib/api/wsdl/wsdl2schema.js +354 -0
- package/lib/browser/canvas.d.ts +12 -0
- package/lib/browser/canvas.js +77 -0
- package/lib/browser/client.d.ts +82 -0
- package/lib/browser/client.js +244 -0
- package/lib/browser/jsonp.d.ts +12 -0
- package/lib/browser/jsonp.js +69 -0
- package/lib/browser/registry.d.ts +3 -0
- package/lib/browser/registry.js +5 -0
- package/lib/browser/request.d.ts +10 -0
- package/lib/browser/request.js +202 -0
- package/lib/cache.d.ts +74 -0
- package/lib/cache.js +159 -0
- package/lib/connection.d.ts +355 -0
- package/lib/connection.js +1153 -0
- package/lib/core.d.ts +17 -0
- package/lib/core.js +55 -0
- package/lib/csv.d.ts +23 -0
- package/lib/csv.js +35 -0
- package/lib/date.d.ts +82 -0
- package/lib/date.js +201 -0
- package/lib/http-api.d.ts +75 -0
- package/lib/http-api.js +257 -0
- package/lib/index.d.ts +12 -0
- package/lib/index.js +31 -0
- package/lib/jsforce.d.ts +26 -0
- package/lib/jsforce.js +67 -0
- package/lib/jwtOAuth2.d.ts +8 -0
- package/lib/jwtOAuth2.js +23 -0
- package/lib/oauth2.d.ts +92 -0
- package/lib/oauth2.js +245 -0
- package/lib/process.d.ts +157 -0
- package/lib/process.js +143 -0
- package/lib/query.d.ts +341 -0
- package/lib/query.js +817 -0
- package/lib/quick-action.d.ts +44 -0
- package/lib/quick-action.js +46 -0
- package/lib/record-reference.d.ts +46 -0
- package/lib/record-reference.js +65 -0
- package/lib/record-stream.d.ts +83 -0
- package/lib/record-stream.js +233 -0
- package/lib/registry/base.d.ts +43 -0
- package/lib/registry/base.js +96 -0
- package/lib/registry/empty.d.ts +7 -0
- package/lib/registry/empty.js +13 -0
- package/lib/registry/file.d.ts +11 -0
- package/lib/registry/file.js +51 -0
- package/lib/registry/index.d.ts +8 -0
- package/lib/registry/index.js +21 -0
- package/lib/registry/sfdx.d.ts +56 -0
- package/lib/registry/sfdx.js +133 -0
- package/lib/registry/types.d.ts +47 -0
- package/lib/registry/types.js +2 -0
- package/lib/request-helper.d.ts +23 -0
- package/lib/request-helper.js +102 -0
- package/lib/request.d.ts +11 -0
- package/lib/request.js +75 -0
- package/lib/session-refresh-delegate.d.ts +31 -0
- package/lib/session-refresh-delegate.js +69 -0
- package/lib/soap.d.ts +60 -0
- package/lib/soap.js +246 -0
- package/lib/sobject.d.ts +258 -0
- package/lib/sobject.js +376 -0
- package/lib/soql-builder.d.ts +25 -0
- package/lib/soql-builder.js +226 -0
- package/lib/transport.d.ts +63 -0
- package/lib/transport.js +175 -0
- package/lib/types/common.d.ts +560 -0
- package/lib/types/common.js +2 -0
- package/lib/types/index.d.ts +7 -0
- package/lib/types/index.js +23 -0
- package/lib/types/projection.d.ts +26 -0
- package/lib/types/projection.js +2 -0
- package/lib/types/record.d.ts +44 -0
- package/lib/types/record.js +2 -0
- package/lib/types/schema.d.ts +50 -0
- package/lib/types/schema.js +2 -0
- package/lib/types/soap.d.ts +43 -0
- package/lib/types/soap.js +2 -0
- package/lib/types/standard-schema.d.ts +16199 -0
- package/lib/types/standard-schema.js +2 -0
- package/lib/types/util.d.ts +7 -0
- package/lib/types/util.js +2 -0
- package/lib/util/formatter.d.ts +8 -0
- package/lib/util/formatter.js +24 -0
- package/lib/util/function.d.ts +32 -0
- package/lib/util/function.js +52 -0
- package/lib/util/logger.d.ts +29 -0
- package/lib/util/logger.js +102 -0
- package/lib/util/promise.d.ts +19 -0
- package/lib/util/promise.js +25 -0
- package/lib/util/stream.d.ts +12 -0
- package/lib/util/stream.js +88 -0
- package/package.json +260 -6
- package/typings/faye/index.d.ts +16 -0
- package/typings/index.d.ts +1 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import Connection from '../connection';
|
|
2
|
+
import { Schema, Record, SoapSchemaDef, SoapSchema } from '../types';
|
|
3
|
+
import { LeadConvert, LeadConvertResult, MergeRequest, MergeResult, EmptyRecycleBinResult, DescribeTabSetResult, GetServerTimestampResult, GetUserInfoResult, ResetPasswordResult, SaveResult, UpsertResult, DeleteResult } from './soap/schema';
|
|
4
|
+
/**
|
|
5
|
+
* API class for Partner SOAP call
|
|
6
|
+
*/
|
|
7
|
+
export declare class SoapApi<S extends Schema> {
|
|
8
|
+
_conn: Connection<S>;
|
|
9
|
+
constructor(conn: Connection<S>);
|
|
10
|
+
/**
|
|
11
|
+
* Call SOAP Api (Partner) endpoint
|
|
12
|
+
* @private
|
|
13
|
+
*/
|
|
14
|
+
_invoke(method: string, message: object, schema: SoapSchema | SoapSchemaDef): Promise<any>;
|
|
15
|
+
/**
|
|
16
|
+
* Converts a Lead into an Account, Contact, or (optionally) an Opportunity.
|
|
17
|
+
*/
|
|
18
|
+
convertLead(leadConverts: Partial<LeadConvert>[]): Promise<LeadConvertResult[]>;
|
|
19
|
+
convertLead(leadConvert: Partial<LeadConvert>): Promise<LeadConvertResult>;
|
|
20
|
+
convertLead(leadConvert: Partial<LeadConvert> | Partial<LeadConvert>[]): Promise<LeadConvertResult | LeadConvertResult[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Merge up to three records into one
|
|
23
|
+
*/
|
|
24
|
+
merge(mergeRequests: Partial<MergeRequest>[]): Promise<MergeResult[]>;
|
|
25
|
+
merge(mergeRequest: Partial<MergeRequest>): Promise<MergeResult>;
|
|
26
|
+
merge(mergeRequest: Partial<MergeRequest> | Partial<MergeRequest>[]): Promise<MergeResult | MergeResult[]>;
|
|
27
|
+
/**
|
|
28
|
+
* Delete records from the recycle bin immediately
|
|
29
|
+
*/
|
|
30
|
+
emptyRecycleBin(ids: string[]): Promise<EmptyRecycleBinResult>;
|
|
31
|
+
/**
|
|
32
|
+
* Returns information about the standard and custom apps available to the logged-in user
|
|
33
|
+
*/
|
|
34
|
+
describeTabs(): Promise<DescribeTabSetResult[]>;
|
|
35
|
+
/**
|
|
36
|
+
* Retrieves the current system timestamp (Coordinated Universal Time (UTC) time zone) from the API
|
|
37
|
+
*/
|
|
38
|
+
getServerTimestamp(): Promise<GetServerTimestampResult>;
|
|
39
|
+
/**
|
|
40
|
+
* Retrieves personal information for the user associated with the current session
|
|
41
|
+
*/
|
|
42
|
+
getUserInfo(): Promise<GetUserInfoResult>;
|
|
43
|
+
/**
|
|
44
|
+
* Sets the specified user’s password to the specified value
|
|
45
|
+
*/
|
|
46
|
+
setPassword(userId: string, password: string): Promise<string>;
|
|
47
|
+
/**
|
|
48
|
+
* Resets the specified user’s password
|
|
49
|
+
*/
|
|
50
|
+
resetPassword(userId: string): Promise<ResetPasswordResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Adds one or more new records to your organization’s data
|
|
53
|
+
*/
|
|
54
|
+
create(sObject: Record[]): Promise<SaveResult[]>;
|
|
55
|
+
create(sObject: Record): Promise<SaveResult>;
|
|
56
|
+
create(sObjects: Record | Record[]): Promise<SaveResult | SaveResult[]>;
|
|
57
|
+
/**
|
|
58
|
+
* Updates one or more existing records in your organization’s data.
|
|
59
|
+
*/
|
|
60
|
+
update(sObject: Record[]): Promise<SaveResult[]>;
|
|
61
|
+
update(sObject: Record): Promise<SaveResult>;
|
|
62
|
+
update(sObjects: Record | Record[]): Promise<SaveResult | SaveResult[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Creates new records and updates existing records in your organization’s data.
|
|
65
|
+
*/
|
|
66
|
+
upsert(externalIdFieldName: string, sObjects: Record[]): Promise<UpsertResult[]>;
|
|
67
|
+
upsert(externalIdFieldName: string, sObject: Record): Promise<UpsertResult>;
|
|
68
|
+
upsert(externalIdFieldName: string, sObjects: Record | Record[]): Promise<UpsertResult | UpsertResult[]>;
|
|
69
|
+
/**
|
|
70
|
+
* Deletes one or more records from your organization’s data
|
|
71
|
+
*/
|
|
72
|
+
delete(ids: string | string[]): Promise<DeleteResult[]>;
|
|
73
|
+
delete(id: string): Promise<DeleteResult>;
|
|
74
|
+
delete(ids: string | string[]): Promise<DeleteResult | DeleteResult[]>;
|
|
75
|
+
}
|
|
76
|
+
export default SoapApi;
|
package/lib/api/soap.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.SoapApi = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* @file Salesforce SOAP API
|
|
9
|
+
* @author Shinichi Tomita <shinichi.tomita@gmail.com>
|
|
10
|
+
*/
|
|
11
|
+
const jsforce_1 = require("../jsforce");
|
|
12
|
+
const soap_1 = __importDefault(require("../soap"));
|
|
13
|
+
const schema_1 = require("./soap/schema");
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
*/
|
|
17
|
+
function toSoapRecord(records) {
|
|
18
|
+
return (Array.isArray(records) ? records : [records]).map((record) => {
|
|
19
|
+
const { type, attributes, ...rec } = record;
|
|
20
|
+
const t = type || attributes?.type;
|
|
21
|
+
if (!t) {
|
|
22
|
+
throw new Error('Given record is not including sObject type information');
|
|
23
|
+
}
|
|
24
|
+
const fieldsToNull = Object.keys(rec).filter((field) => record[field] === null);
|
|
25
|
+
for (const field of fieldsToNull) {
|
|
26
|
+
delete rec[field];
|
|
27
|
+
}
|
|
28
|
+
return fieldsToNull.length > 0
|
|
29
|
+
? { type: t, fieldsToNull, ...rec }
|
|
30
|
+
: { type: t, ...rec };
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* API class for Partner SOAP call
|
|
35
|
+
*/
|
|
36
|
+
class SoapApi {
|
|
37
|
+
_conn;
|
|
38
|
+
constructor(conn) {
|
|
39
|
+
this._conn = conn;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Call SOAP Api (Partner) endpoint
|
|
43
|
+
* @private
|
|
44
|
+
*/
|
|
45
|
+
async _invoke(method, message, schema) {
|
|
46
|
+
const soapEndpoint = new soap_1.default(this._conn, {
|
|
47
|
+
xmlns: 'urn:partner.soap.sforce.com',
|
|
48
|
+
endpointUrl: `${this._conn.instanceUrl}/services/Soap/u/${this._conn.version}`,
|
|
49
|
+
});
|
|
50
|
+
const res = await soapEndpoint.invoke(method, message, schema ? { result: schema } : undefined, schema_1.ApiSchemas);
|
|
51
|
+
return res.result;
|
|
52
|
+
}
|
|
53
|
+
async convertLead(leadConverts) {
|
|
54
|
+
const schema = Array.isArray(leadConverts)
|
|
55
|
+
? [schema_1.ApiSchemas.LeadConvertResult]
|
|
56
|
+
: schema_1.ApiSchemas.LeadConvertResult;
|
|
57
|
+
return this._invoke('convertLead', { leadConverts }, schema);
|
|
58
|
+
}
|
|
59
|
+
async merge(mergeRequests) {
|
|
60
|
+
const schema = Array.isArray(mergeRequests)
|
|
61
|
+
? [schema_1.ApiSchemas.MergeResult]
|
|
62
|
+
: schema_1.ApiSchemas.MergeResult;
|
|
63
|
+
return this._invoke('merge', { mergeRequests }, schema);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Delete records from the recycle bin immediately
|
|
67
|
+
*/
|
|
68
|
+
async emptyRecycleBin(ids) {
|
|
69
|
+
return this._invoke('emptyRecycleBin', { ids }, [
|
|
70
|
+
schema_1.ApiSchemas.EmptyRecycleBinResult,
|
|
71
|
+
]);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Returns information about the standard and custom apps available to the logged-in user
|
|
75
|
+
*/
|
|
76
|
+
async describeTabs() {
|
|
77
|
+
return this._invoke('describeTabs', {}, [schema_1.ApiSchemas.DescribeTabSetResult]);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Retrieves the current system timestamp (Coordinated Universal Time (UTC) time zone) from the API
|
|
81
|
+
*/
|
|
82
|
+
async getServerTimestamp() {
|
|
83
|
+
return this._invoke('getServerTimestamp', {}, schema_1.ApiSchemas.GetServerTimestampResult);
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Retrieves personal information for the user associated with the current session
|
|
87
|
+
*/
|
|
88
|
+
async getUserInfo() {
|
|
89
|
+
return this._invoke('getUserInfo', {}, schema_1.ApiSchemas.GetUserInfoResult);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Sets the specified user’s password to the specified value
|
|
93
|
+
*/
|
|
94
|
+
setPassword(userId, password) {
|
|
95
|
+
return this._invoke('setPassword', { userId, password }, 'string');
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Resets the specified user’s password
|
|
99
|
+
*/
|
|
100
|
+
resetPassword(userId) {
|
|
101
|
+
return this._invoke('resetPassword', { userId }, schema_1.ApiSchemas.ResetPasswordResult);
|
|
102
|
+
}
|
|
103
|
+
create(sObjects) {
|
|
104
|
+
const schema = Array.isArray(sObjects)
|
|
105
|
+
? [schema_1.ApiSchemas.SaveResult]
|
|
106
|
+
: schema_1.ApiSchemas.SaveResult;
|
|
107
|
+
const args = {
|
|
108
|
+
'@xmlns': 'urn:partner.soap.sforce.com',
|
|
109
|
+
'@xmlns:ns1': 'sobject.partner.soap.sforce.com',
|
|
110
|
+
'ns1:sObjects': toSoapRecord(sObjects),
|
|
111
|
+
};
|
|
112
|
+
return this._invoke('create', args, schema);
|
|
113
|
+
}
|
|
114
|
+
update(sObjects) {
|
|
115
|
+
const schema = Array.isArray(sObjects)
|
|
116
|
+
? [schema_1.ApiSchemas.SaveResult]
|
|
117
|
+
: schema_1.ApiSchemas.SaveResult;
|
|
118
|
+
const args = {
|
|
119
|
+
'@xmlns': 'urn:partner.soap.sforce.com',
|
|
120
|
+
'@xmlns:ns1': 'sobject.partner.soap.sforce.com',
|
|
121
|
+
'ns1:sObjects': toSoapRecord(sObjects),
|
|
122
|
+
};
|
|
123
|
+
return this._invoke('update', args, schema);
|
|
124
|
+
}
|
|
125
|
+
upsert(externalIdFieldName, sObjects) {
|
|
126
|
+
const schema = Array.isArray(sObjects)
|
|
127
|
+
? [schema_1.ApiSchemas.UpsertResult]
|
|
128
|
+
: schema_1.ApiSchemas.UpsertResult;
|
|
129
|
+
const args = {
|
|
130
|
+
'@xmlns': 'urn:partner.soap.sforce.com',
|
|
131
|
+
'@xmlns:ns1': 'sobject.partner.soap.sforce.com',
|
|
132
|
+
'ns1:externalIDFieldName': externalIdFieldName,
|
|
133
|
+
'ns1:sObjects': toSoapRecord(sObjects),
|
|
134
|
+
};
|
|
135
|
+
return this._invoke('upsert', args, schema);
|
|
136
|
+
}
|
|
137
|
+
delete(ids) {
|
|
138
|
+
const schema = Array.isArray(ids)
|
|
139
|
+
? [schema_1.ApiSchemas.DeleteResult]
|
|
140
|
+
: schema_1.ApiSchemas.DeleteResult;
|
|
141
|
+
const args = {
|
|
142
|
+
'@xmlns': 'urn:partner.soap.sforce.com',
|
|
143
|
+
'@xmlns:ns1': 'sobject.partner.soap.sforce.com',
|
|
144
|
+
'ns1:ids': ids,
|
|
145
|
+
};
|
|
146
|
+
return this._invoke('delete', args, schema);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
exports.SoapApi = SoapApi;
|
|
150
|
+
/*--------------------------------------------*/
|
|
151
|
+
/*
|
|
152
|
+
* Register hook in connection instantiation for dynamically adding this API module features
|
|
153
|
+
*/
|
|
154
|
+
(0, jsforce_1.registerModule)('soap', (conn) => new SoapApi(conn));
|
|
155
|
+
exports.default = SoapApi;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Faye Client extensions: https://faye.jcoglan.com/browser/extensions.html
|
|
3
|
+
*
|
|
4
|
+
* For use with Streaming.prototype.createClient()
|
|
5
|
+
**/
|
|
6
|
+
/**
|
|
7
|
+
* Constructor for an auth failure detector extension
|
|
8
|
+
*
|
|
9
|
+
* Based on new feature released with Salesforce Spring '18:
|
|
10
|
+
* https://releasenotes.docs.salesforce.com/en-us/spring18/release-notes/rn_messaging_cometd_auth_validation.htm?edition=&impact=
|
|
11
|
+
*
|
|
12
|
+
* Example triggering error message:
|
|
13
|
+
*
|
|
14
|
+
* ```
|
|
15
|
+
* {
|
|
16
|
+
* "ext":{
|
|
17
|
+
* "sfdc":{"failureReason":"401::Authentication invalid"},
|
|
18
|
+
* "replay":true},
|
|
19
|
+
* "advice":{"reconnect":"none"},
|
|
20
|
+
* "channel":"/meta/handshake",
|
|
21
|
+
* "error":"403::Handshake denied",
|
|
22
|
+
* "successful":false
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* Example usage:
|
|
27
|
+
*
|
|
28
|
+
* ```javascript
|
|
29
|
+
* const jsforce = require('jsforce');
|
|
30
|
+
* const { StreamingExtension } = require('jsforce/api/streaming');
|
|
31
|
+
*
|
|
32
|
+
* const conn = new jsforce.Connection({ … });
|
|
33
|
+
*
|
|
34
|
+
* const channel = "/event/My_Event__e";
|
|
35
|
+
*
|
|
36
|
+
* // Exit the Node process when auth fails
|
|
37
|
+
* const exitCallback = () => process.exit(1);
|
|
38
|
+
* const authFailureExt = new StreamingExtension.AuthFailure(exitCallback);
|
|
39
|
+
*
|
|
40
|
+
* const fayeClient = conn.streaming.createClient([ authFailureExt ]);
|
|
41
|
+
*
|
|
42
|
+
* const subscription = fayeClient.subscribe(channel, data => {
|
|
43
|
+
* console.log('topic received data', data);
|
|
44
|
+
* });
|
|
45
|
+
*
|
|
46
|
+
* subscription.cancel();
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @param {Function} failureCallback - Invoked when authentication becomes invalid
|
|
50
|
+
*/
|
|
51
|
+
export declare class AuthFailure {
|
|
52
|
+
_failureCallback: Function;
|
|
53
|
+
constructor(failureCallback: Function);
|
|
54
|
+
incoming(message: any, callback: Function): void;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Constructor for a durable streaming replay extension
|
|
58
|
+
*
|
|
59
|
+
* Modified from original Salesforce demo source code:
|
|
60
|
+
* https://github.com/developerforce/SalesforceDurableStreamingDemo/blob/3d4a56eac956f744ad6c22e6a8141b6feb57abb9/staticresources/cometdReplayExtension.resource
|
|
61
|
+
*
|
|
62
|
+
* Example usage:
|
|
63
|
+
*
|
|
64
|
+
* ```javascript
|
|
65
|
+
* const jsforce = require('jsforce');
|
|
66
|
+
* const { StreamingExtension } = require('jsforce/api/streaming');
|
|
67
|
+
|
|
68
|
+
* const conn = new jsforce.Connection({ … });
|
|
69
|
+
*
|
|
70
|
+
* const channel = "/event/My_Event__e";
|
|
71
|
+
* const replayId = -2; // -2 is all retained events
|
|
72
|
+
*
|
|
73
|
+
* const replayExt = new StreamingExtension.Replay(channel, replayId);
|
|
74
|
+
*
|
|
75
|
+
* const fayeClient = conn.streaming.createClient([ replayExt ]);
|
|
76
|
+
*
|
|
77
|
+
* const subscription = fayeClient.subscribe(channel, data => {
|
|
78
|
+
* console.log('topic received data', data);
|
|
79
|
+
* });
|
|
80
|
+
*
|
|
81
|
+
* subscription.cancel();
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export declare class Replay {
|
|
85
|
+
_extensionEnabled: boolean;
|
|
86
|
+
_replay: number | null | undefined;
|
|
87
|
+
_channel: string;
|
|
88
|
+
constructor(channel: string, replayId?: number | null);
|
|
89
|
+
setExtensionEnabled(extensionEnabled: boolean): void;
|
|
90
|
+
setReplay(replay: string): void;
|
|
91
|
+
setChannel(channel: string): void;
|
|
92
|
+
incoming(message: any, callback: Function): void;
|
|
93
|
+
outgoing(message: any, callback: Function): void;
|
|
94
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Faye Client extensions: https://faye.jcoglan.com/browser/extensions.html
|
|
4
|
+
*
|
|
5
|
+
* For use with Streaming.prototype.createClient()
|
|
6
|
+
**/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.Replay = exports.AuthFailure = void 0;
|
|
9
|
+
/*-------------------------------------------*/
|
|
10
|
+
/**
|
|
11
|
+
* Constructor for an auth failure detector extension
|
|
12
|
+
*
|
|
13
|
+
* Based on new feature released with Salesforce Spring '18:
|
|
14
|
+
* https://releasenotes.docs.salesforce.com/en-us/spring18/release-notes/rn_messaging_cometd_auth_validation.htm?edition=&impact=
|
|
15
|
+
*
|
|
16
|
+
* Example triggering error message:
|
|
17
|
+
*
|
|
18
|
+
* ```
|
|
19
|
+
* {
|
|
20
|
+
* "ext":{
|
|
21
|
+
* "sfdc":{"failureReason":"401::Authentication invalid"},
|
|
22
|
+
* "replay":true},
|
|
23
|
+
* "advice":{"reconnect":"none"},
|
|
24
|
+
* "channel":"/meta/handshake",
|
|
25
|
+
* "error":"403::Handshake denied",
|
|
26
|
+
* "successful":false
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Example usage:
|
|
31
|
+
*
|
|
32
|
+
* ```javascript
|
|
33
|
+
* const jsforce = require('jsforce');
|
|
34
|
+
* const { StreamingExtension } = require('jsforce/api/streaming');
|
|
35
|
+
*
|
|
36
|
+
* const conn = new jsforce.Connection({ … });
|
|
37
|
+
*
|
|
38
|
+
* const channel = "/event/My_Event__e";
|
|
39
|
+
*
|
|
40
|
+
* // Exit the Node process when auth fails
|
|
41
|
+
* const exitCallback = () => process.exit(1);
|
|
42
|
+
* const authFailureExt = new StreamingExtension.AuthFailure(exitCallback);
|
|
43
|
+
*
|
|
44
|
+
* const fayeClient = conn.streaming.createClient([ authFailureExt ]);
|
|
45
|
+
*
|
|
46
|
+
* const subscription = fayeClient.subscribe(channel, data => {
|
|
47
|
+
* console.log('topic received data', data);
|
|
48
|
+
* });
|
|
49
|
+
*
|
|
50
|
+
* subscription.cancel();
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @param {Function} failureCallback - Invoked when authentication becomes invalid
|
|
54
|
+
*/
|
|
55
|
+
class AuthFailure {
|
|
56
|
+
_failureCallback;
|
|
57
|
+
constructor(failureCallback) {
|
|
58
|
+
this._failureCallback = failureCallback;
|
|
59
|
+
}
|
|
60
|
+
incoming(message, callback) {
|
|
61
|
+
if ((message.channel === '/meta/connect' ||
|
|
62
|
+
message.channel === '/meta/handshake') &&
|
|
63
|
+
message.advice &&
|
|
64
|
+
message.advice.reconnect == 'none') {
|
|
65
|
+
this._failureCallback(message);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
callback(message);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.AuthFailure = AuthFailure;
|
|
73
|
+
/*-------------------------------------------*/
|
|
74
|
+
const REPLAY_FROM_KEY = 'replay';
|
|
75
|
+
/**
|
|
76
|
+
* Constructor for a durable streaming replay extension
|
|
77
|
+
*
|
|
78
|
+
* Modified from original Salesforce demo source code:
|
|
79
|
+
* https://github.com/developerforce/SalesforceDurableStreamingDemo/blob/3d4a56eac956f744ad6c22e6a8141b6feb57abb9/staticresources/cometdReplayExtension.resource
|
|
80
|
+
*
|
|
81
|
+
* Example usage:
|
|
82
|
+
*
|
|
83
|
+
* ```javascript
|
|
84
|
+
* const jsforce = require('jsforce');
|
|
85
|
+
* const { StreamingExtension } = require('jsforce/api/streaming');
|
|
86
|
+
|
|
87
|
+
* const conn = new jsforce.Connection({ … });
|
|
88
|
+
*
|
|
89
|
+
* const channel = "/event/My_Event__e";
|
|
90
|
+
* const replayId = -2; // -2 is all retained events
|
|
91
|
+
*
|
|
92
|
+
* const replayExt = new StreamingExtension.Replay(channel, replayId);
|
|
93
|
+
*
|
|
94
|
+
* const fayeClient = conn.streaming.createClient([ replayExt ]);
|
|
95
|
+
*
|
|
96
|
+
* const subscription = fayeClient.subscribe(channel, data => {
|
|
97
|
+
* console.log('topic received data', data);
|
|
98
|
+
* });
|
|
99
|
+
*
|
|
100
|
+
* subscription.cancel();
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
class Replay {
|
|
104
|
+
_extensionEnabled;
|
|
105
|
+
_replay;
|
|
106
|
+
_channel;
|
|
107
|
+
constructor(channel, replayId) {
|
|
108
|
+
this._extensionEnabled = replayId != null;
|
|
109
|
+
this._channel = channel;
|
|
110
|
+
this._replay = replayId;
|
|
111
|
+
}
|
|
112
|
+
setExtensionEnabled(extensionEnabled) {
|
|
113
|
+
this._extensionEnabled = extensionEnabled;
|
|
114
|
+
}
|
|
115
|
+
setReplay(replay) {
|
|
116
|
+
this._replay = parseInt(replay, 10);
|
|
117
|
+
}
|
|
118
|
+
setChannel(channel) {
|
|
119
|
+
this._channel = channel;
|
|
120
|
+
}
|
|
121
|
+
incoming(message, callback) {
|
|
122
|
+
if (message.channel === '/meta/handshake') {
|
|
123
|
+
if (message.ext && message.ext[REPLAY_FROM_KEY] == true) {
|
|
124
|
+
this._extensionEnabled = true;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else if (message.channel === this._channel &&
|
|
128
|
+
message.data &&
|
|
129
|
+
message.data.event &&
|
|
130
|
+
message.data.event.replayId) {
|
|
131
|
+
this._replay = message.data.event.replayId;
|
|
132
|
+
}
|
|
133
|
+
callback(message);
|
|
134
|
+
}
|
|
135
|
+
outgoing(message, callback) {
|
|
136
|
+
if (message.channel === '/meta/subscribe') {
|
|
137
|
+
if (this._extensionEnabled) {
|
|
138
|
+
if (!message.ext) {
|
|
139
|
+
message.ext = {};
|
|
140
|
+
}
|
|
141
|
+
const replayFromMap = {
|
|
142
|
+
[this._channel]: this._replay,
|
|
143
|
+
};
|
|
144
|
+
// add "ext : { "replay" : { CHANNEL : REPLAY_VALUE }}" to subscribe message
|
|
145
|
+
message.ext[REPLAY_FROM_KEY] = replayFromMap;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
callback(message);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.Replay = Replay;
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
/**
|
|
3
|
+
* @file Manages Streaming APIs
|
|
4
|
+
* @author Shinichi Tomita <shinichi.tomita@gmail.com>
|
|
5
|
+
*/
|
|
6
|
+
import { EventEmitter } from 'events';
|
|
7
|
+
import { Client, Subscription } from 'faye';
|
|
8
|
+
import Connection from '../connection';
|
|
9
|
+
import { Record, Schema } from '../types';
|
|
10
|
+
import * as StreamingExtension from './streaming/extension';
|
|
11
|
+
/**
|
|
12
|
+
*
|
|
13
|
+
*/
|
|
14
|
+
export type StreamingMessage<R extends Record> = {
|
|
15
|
+
event: {
|
|
16
|
+
type: string;
|
|
17
|
+
createdDate: string;
|
|
18
|
+
replayId: number;
|
|
19
|
+
};
|
|
20
|
+
sobject: R;
|
|
21
|
+
};
|
|
22
|
+
export type GenericStreamingMessage = {
|
|
23
|
+
event: {
|
|
24
|
+
createdDate: string;
|
|
25
|
+
replayId: number;
|
|
26
|
+
};
|
|
27
|
+
payload: string;
|
|
28
|
+
};
|
|
29
|
+
export type PushEvent = {
|
|
30
|
+
payload: string;
|
|
31
|
+
userIds: string[];
|
|
32
|
+
};
|
|
33
|
+
export type PushEventResult = {
|
|
34
|
+
fanoutCount: number;
|
|
35
|
+
userOnlineStatus: {
|
|
36
|
+
[userId: string]: boolean;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
export { Client, Subscription };
|
|
40
|
+
/**
|
|
41
|
+
* Streaming API topic class
|
|
42
|
+
*/
|
|
43
|
+
declare class Topic<S extends Schema, R extends Record> {
|
|
44
|
+
_streaming: Streaming<S>;
|
|
45
|
+
name: string;
|
|
46
|
+
constructor(streaming: Streaming<S>, name: string);
|
|
47
|
+
/**
|
|
48
|
+
* Subscribe listener to topic
|
|
49
|
+
*/
|
|
50
|
+
subscribe(listener: (message: StreamingMessage<R>) => void): Subscription;
|
|
51
|
+
/**
|
|
52
|
+
* Unsubscribe listener from topic
|
|
53
|
+
*/
|
|
54
|
+
unsubscribe(subscr: Subscription): this;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Streaming API Generic Streaming Channel
|
|
58
|
+
*/
|
|
59
|
+
declare class Channel<S extends Schema> {
|
|
60
|
+
_streaming: Streaming<S>;
|
|
61
|
+
_id: Promise<string | undefined> | undefined;
|
|
62
|
+
name: string;
|
|
63
|
+
constructor(streaming: Streaming<S>, name: string);
|
|
64
|
+
/**
|
|
65
|
+
* Subscribe to channel
|
|
66
|
+
*/
|
|
67
|
+
subscribe(listener: Function): Subscription;
|
|
68
|
+
unsubscribe(subscr: Subscription): this;
|
|
69
|
+
push(events: PushEvent): Promise<PushEventResult>;
|
|
70
|
+
push(events: PushEvent): Promise<PushEventResult[]>;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Streaming API class
|
|
74
|
+
*/
|
|
75
|
+
export declare class Streaming<S extends Schema> extends EventEmitter {
|
|
76
|
+
_conn: Connection<S>;
|
|
77
|
+
_topics: {
|
|
78
|
+
[name: string]: Topic<S, Record>;
|
|
79
|
+
};
|
|
80
|
+
_fayeClients: {
|
|
81
|
+
[clientType: string]: Client;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
*
|
|
85
|
+
*/
|
|
86
|
+
constructor(conn: Connection<S>);
|
|
87
|
+
_createClient(forChannelName?: string | null, extensions?: any[]): Client;
|
|
88
|
+
/** @private **/
|
|
89
|
+
_getFayeClient(channelName: string): Client;
|
|
90
|
+
/**
|
|
91
|
+
* Get named topic
|
|
92
|
+
*/
|
|
93
|
+
topic<R extends Record = Record>(name: string): Topic<S, R>;
|
|
94
|
+
/**
|
|
95
|
+
* Get channel for channel name
|
|
96
|
+
*/
|
|
97
|
+
channel(name: string): Channel<S>;
|
|
98
|
+
/**
|
|
99
|
+
* Subscribe topic/channel
|
|
100
|
+
*/
|
|
101
|
+
subscribe(name: string, listener: Function): Subscription;
|
|
102
|
+
/**
|
|
103
|
+
* Unsubscribe topic
|
|
104
|
+
*/
|
|
105
|
+
unsubscribe(name: string, subscription: Subscription): this;
|
|
106
|
+
/**
|
|
107
|
+
* Create a Streaming client, optionally with extensions
|
|
108
|
+
*
|
|
109
|
+
* See Faye docs for implementation details: https://faye.jcoglan.com/browser/extensions.html
|
|
110
|
+
*
|
|
111
|
+
* Example usage:
|
|
112
|
+
*
|
|
113
|
+
* ```javascript
|
|
114
|
+
* const jsforce = require('jsforce');
|
|
115
|
+
*
|
|
116
|
+
* // Establish a Salesforce connection. (Details elided)
|
|
117
|
+
* const conn = new jsforce.Connection({ … });
|
|
118
|
+
*
|
|
119
|
+
* const fayeClient = conn.streaming.createClient();
|
|
120
|
+
*
|
|
121
|
+
* const subscription = fayeClient.subscribe(channel, data => {
|
|
122
|
+
* console.log('topic received data', data);
|
|
123
|
+
* });
|
|
124
|
+
*
|
|
125
|
+
* subscription.cancel();
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* Example with extensions, using Replay & Auth Failure extensions in a server-side Node.js app:
|
|
129
|
+
*
|
|
130
|
+
* ```javascript
|
|
131
|
+
* const jsforce = require('jsforce');
|
|
132
|
+
* const { StreamingExtension } = require('jsforce/api/streaming');
|
|
133
|
+
*
|
|
134
|
+
* // Establish a Salesforce connection. (Details elided)
|
|
135
|
+
* const conn = new jsforce.Connection({ … });
|
|
136
|
+
*
|
|
137
|
+
* const channel = "/event/My_Event__e";
|
|
138
|
+
* const replayId = -2; // -2 is all retained events
|
|
139
|
+
*
|
|
140
|
+
* const exitCallback = () => process.exit(1);
|
|
141
|
+
* const authFailureExt = new StreamingExtension.AuthFailure(exitCallback);
|
|
142
|
+
*
|
|
143
|
+
* const replayExt = new StreamingExtension.Replay(channel, replayId);
|
|
144
|
+
*
|
|
145
|
+
* const fayeClient = conn.streaming.createClient([
|
|
146
|
+
* authFailureExt,
|
|
147
|
+
* replayExt
|
|
148
|
+
* ]);
|
|
149
|
+
*
|
|
150
|
+
* const subscription = fayeClient.subscribe(channel, data => {
|
|
151
|
+
* console.log('topic received data', data);
|
|
152
|
+
* });
|
|
153
|
+
*
|
|
154
|
+
* subscription.cancel();
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
createClient(extensions: any[]): Client;
|
|
158
|
+
}
|
|
159
|
+
export { StreamingExtension };
|
|
160
|
+
export default Streaming;
|