@salesforce/core 3.7.2 → 3.7.3

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/lib/org/org.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.Org = void 0;
9
+ exports.Org = exports.SandboxEvents = exports.OrgTypes = void 0;
10
10
  const path_1 = require("path");
11
11
  const kit_1 = require("@salesforce/kit");
12
12
  const ts_types_1 = require("@salesforce/ts-types");
@@ -21,11 +21,37 @@ const fs_1 = require("../util/fs");
21
21
  const sfdc_1 = require("../util/sfdc");
22
22
  const globalInfo_1 = require("../globalInfo");
23
23
  const messages_1 = require("../messages");
24
+ const lifecycleEvents_1 = require("../lifecycleEvents");
25
+ const webOAuthServer_1 = require("../webOAuthServer");
24
26
  const connection_1 = require("./connection");
25
27
  const authInfo_1 = require("./authInfo");
26
28
  const orgConfigProperties_1 = require("./orgConfigProperties");
27
29
  messages_1.Messages.importMessagesDirectory(__dirname);
28
- const messages = messages_1.Messages.load('@salesforce/core', 'org', ['notADevHub', 'noUsernameFound']);
30
+ const messages = messages_1.Messages.load('@salesforce/core', 'org', [
31
+ 'deleteOrgHubError',
32
+ 'insufficientAccessToDelete',
33
+ 'missingAuthUsername',
34
+ 'noDevHubFound',
35
+ 'notADevHub',
36
+ 'noUsernameFound',
37
+ 'orgPollingTimeout',
38
+ 'sandboxDeleteFailed',
39
+ 'sandboxInfoCreateFailed',
40
+ 'sandboxNotFound',
41
+ 'scratchOrgNotFound',
42
+ ]);
43
+ var OrgTypes;
44
+ (function (OrgTypes) {
45
+ OrgTypes["Scratch"] = "scratch";
46
+ OrgTypes["Sandbox"] = "sandbox";
47
+ })(OrgTypes = exports.OrgTypes || (exports.OrgTypes = {}));
48
+ var SandboxEvents;
49
+ (function (SandboxEvents) {
50
+ SandboxEvents["EVENT_STATUS"] = "status";
51
+ SandboxEvents["EVENT_ASYNC_RESULT"] = "asyncResult";
52
+ SandboxEvents["EVENT_RESULT"] = "result";
53
+ SandboxEvents["EVENT_AUTH"] = "auth";
54
+ })(SandboxEvents = exports.SandboxEvents || (exports.SandboxEvents = {}));
29
55
  /**
30
56
  * Provides a way to manage a locally authenticated Org.
31
57
  *
@@ -61,6 +87,33 @@ class Org extends kit_1.AsyncOptionalCreatable {
61
87
  this.status = Org.Status.UNKNOWN;
62
88
  this.options = options || {};
63
89
  }
90
+ /**
91
+ * create a sandbox from a production org
92
+ * 'this' needs to be a production org with sandbox licenses available
93
+ *
94
+ * @param sandboxReq SandboxRequest options to create the sandbox with
95
+ * @param options Wait: The amount of time to wait before timing out, Interval: The time interval between polling
96
+ */
97
+ async createSandbox(sandboxReq, options) {
98
+ var _a;
99
+ this.logger.debug('CreateSandbox called with SandboxRequest: %s ', sandboxReq);
100
+ const createResult = await this.connection.tooling.create('SandboxInfo', sandboxReq);
101
+ this.logger.debug('Return from calling tooling.create: %s ', createResult);
102
+ if (Array.isArray(createResult) || !createResult.success) {
103
+ throw messages.createError('sandboxInfoCreateFailed', [JSON.stringify(createResult)]);
104
+ }
105
+ const sandboxCreationProgress = await this.querySandboxProcess(createResult.id);
106
+ this.logger.debug('Return from calling singleRecordQuery with tooling: %s', sandboxCreationProgress);
107
+ const retries = options.wait ? options.wait.seconds / kit_1.Duration.seconds(30).seconds : 0;
108
+ this.logger.debug('pollStatusAndAuth sandboxProcessObj %s, maxPollingRetries %i', sandboxCreationProgress, retries);
109
+ const pollInterval = (_a = options.interval) !== null && _a !== void 0 ? _a : kit_1.Duration.seconds(30);
110
+ return this.pollStatusAndAuth({
111
+ sandboxProcessObj: sandboxCreationProgress,
112
+ retries,
113
+ shouldPoll: retries > 0,
114
+ pollInterval,
115
+ });
116
+ }
64
117
  /**
65
118
  * Clean all data files in the org's data path. Usually <workspace>/.sfdx/orgs/<username>.
66
119
  *
@@ -75,7 +128,7 @@ class Org extends kit_1.AsyncOptionalCreatable {
75
128
  this.logger.debug(`cleaning data for path: ${dataPath}`);
76
129
  }
77
130
  catch (err) {
78
- if (err.name === 'InvalidProjectWorkspaceError') {
131
+ if (err instanceof Error && err.name === 'InvalidProjectWorkspaceError') {
79
132
  // If we aren't in a project dir, we can't clean up data files.
80
133
  // If the user unlink this org outside of the workspace they used it in,
81
134
  // data files will be left over.
@@ -113,6 +166,13 @@ class Org extends kit_1.AsyncOptionalCreatable {
113
166
  // So, just in case no users are added to this org we will try the remove again.
114
167
  await this.removeAuth();
115
168
  }
169
+ /**
170
+ * Check if org is a sandbox org by checking its SandboxOrgConfig.
171
+ *
172
+ */
173
+ async isSandbox() {
174
+ return !!(await this.getSandboxOrgConfigField(sandboxOrgConfig_1.SandboxOrgConfig.Fields.PROD_ORG_USERNAME));
175
+ }
116
176
  /**
117
177
  * Check that this org is a scratch org by asking the dev hub if it knows about it.
118
178
  *
@@ -138,7 +198,7 @@ class Org extends kit_1.AsyncOptionalCreatable {
138
198
  }
139
199
  }
140
200
  catch (err) {
141
- if (err.name === 'INVALID_TYPE') {
201
+ if (err instanceof Error && err.name === 'INVALID_TYPE') {
142
202
  throw messages.createError('notADevHub', [devHubConnection.getUsername()]);
143
203
  }
144
204
  throw err;
@@ -177,6 +237,36 @@ class Org extends kit_1.AsyncOptionalCreatable {
177
237
  return false;
178
238
  }
179
239
  }
240
+ /**
241
+ * Will delete 'this' instance remotely and any files locally
242
+ *
243
+ * @param controllingOrg username or Org that 'this.devhub' or 'this.production' refers to. AKA a DevHub for a scratch org, or a Production Org for a sandbox
244
+ */
245
+ async deleteFrom(controllingOrg) {
246
+ if (typeof controllingOrg === 'string') {
247
+ controllingOrg = await Org.create({
248
+ aggregator: this.configAggregator,
249
+ aliasOrUsername: controllingOrg,
250
+ });
251
+ }
252
+ if (await this.isSandbox()) {
253
+ await this.deleteSandbox(controllingOrg);
254
+ }
255
+ else {
256
+ await this.deleteScratchOrg(controllingOrg);
257
+ }
258
+ }
259
+ /**
260
+ * Will delete 'this' instance remotely and any files locally
261
+ */
262
+ async delete() {
263
+ if (await this.isSandbox()) {
264
+ await this.deleteSandbox();
265
+ }
266
+ else {
267
+ await this.deleteScratchOrg();
268
+ }
269
+ }
180
270
  /**
181
271
  * Returns `true` if the org is a Dev Hub.
182
272
  *
@@ -243,22 +333,6 @@ class Org extends kit_1.AsyncOptionalCreatable {
243
333
  }
244
334
  return cache;
245
335
  }
246
- /**
247
- * Returns `true` if the org is a sandbox.
248
- *
249
- * **Note** This relies on a cached value in the auth file. If that property
250
- * is not cached, this method will **always return false even if the org is a
251
- * sandbox**. If you need accuracy, use the {@link Org.determineIfDevHubOrg} method.
252
- */
253
- isSandbox() {
254
- const isSandbox = this.getField(Org.Fields.IS_SANDBOX);
255
- if (ts_types_1.isBoolean(isSandbox)) {
256
- return isSandbox;
257
- }
258
- else {
259
- return false;
260
- }
261
- }
262
336
  /**
263
337
  * Returns `true` if the org is a sandbox.
264
338
  *
@@ -502,7 +576,7 @@ class Org extends kit_1.AsyncOptionalCreatable {
502
576
  }
503
577
  this.connection = await connection_1.Connection.create({
504
578
  // If no username is provided or resolvable from an alias, AuthInfo will throw an SfdxError.
505
- authInfo: await authInfo_1.AuthInfo.create({ username }),
579
+ authInfo: await authInfo_1.AuthInfo.create({ username, isDevHub: this.options.isDevHub }),
506
580
  });
507
581
  }
508
582
  else {
@@ -516,6 +590,105 @@ class Org extends kit_1.AsyncOptionalCreatable {
516
590
  getDefaultOptions() {
517
591
  throw new sfdxError_1.SfdxError('Not Supported', 'NotSupportedError');
518
592
  }
593
+ async queryProduction(org, field, value) {
594
+ return org.connection.singleRecordQuery(`SELECT SandboxInfoId FROM SandboxProcess WHERE ${field} ='${value}' AND Status NOT IN ('D', 'E')`, { tooling: true });
595
+ }
596
+ async destorySandbox(org, id) {
597
+ return org.getConnection().tooling.delete('SandboxInfo', id);
598
+ }
599
+ async destoryScratchOrg(org, id) {
600
+ return org.getConnection().delete('ActiveScratchOrg', id);
601
+ }
602
+ /**
603
+ * this method will delete the sandbox org from the production org and clean up any local files
604
+ *
605
+ * @param prodOrg - Production org associated with this sandbox
606
+ * @private
607
+ */
608
+ async deleteSandbox(prodOrg) {
609
+ prodOrg !== null && prodOrg !== void 0 ? prodOrg : (prodOrg = await Org.create({
610
+ aggregator: this.configAggregator,
611
+ aliasOrUsername: await this.getSandboxOrgConfigField(sandboxOrgConfig_1.SandboxOrgConfig.Fields.PROD_ORG_USERNAME),
612
+ }));
613
+ let result;
614
+ // attempt to locate sandbox id by username
615
+ try {
616
+ // try to calculate sandbox name from the production org
617
+ // production org: admin@integrationtesthub.org
618
+ // this.getUsername: admin@integrationtesthub.org.dev1
619
+ // sandboxName in Production: dev1
620
+ const sandboxName = (this.getUsername() || '').split(`${prodOrg.getUsername()}.`)[1];
621
+ if (!sandboxName) {
622
+ this.logger.debug('Could not construct a sandbox name');
623
+ throw new Error();
624
+ }
625
+ this.logger.debug(`attempting to locate sandbox with username ${sandboxName}`);
626
+ result = await this.queryProduction(prodOrg, 'SandboxName', sandboxName);
627
+ if (!result) {
628
+ this.logger.debug(`Failed to find sandbox with username: ${sandboxName}`);
629
+ throw new Error();
630
+ }
631
+ }
632
+ catch {
633
+ // if an error is thrown, don't panic yet. we'll try querying by orgId
634
+ const trimmedId = sfdc_1.sfdc.trimTo15(this.getOrgId());
635
+ this.logger.debug(`defaulting to trimming id from ${this.getOrgId()} to ${trimmedId}`);
636
+ try {
637
+ result = await this.queryProduction(prodOrg, 'SandboxOrganization', trimmedId);
638
+ }
639
+ catch {
640
+ throw messages.createError('sandboxNotFound', [trimmedId]);
641
+ }
642
+ }
643
+ // const deleteResult = await prodOrg.connection.tooling.delete('SandboxInfo', result.SandboxInfoId);
644
+ const deleteResult = await this.destorySandbox(prodOrg, result.SandboxInfoId);
645
+ this.logger.debug('Return from calling tooling.delete: %o ', deleteResult);
646
+ await this.remove();
647
+ if (Array.isArray(deleteResult) || !deleteResult.success) {
648
+ throw messages.createError('sandboxDeleteFailed', [JSON.stringify(deleteResult)]);
649
+ }
650
+ }
651
+ /**
652
+ * If this Org is a scratch org, calling this method will delete the scratch org from the DevHub and clean up any local files
653
+ *
654
+ * @param devHub - optional DevHub Org of the to-be-deleted scratch org
655
+ * @private
656
+ */
657
+ async deleteScratchOrg(devHub) {
658
+ // if we didn't get a devHub, we'll get it from the this org
659
+ devHub !== null && devHub !== void 0 ? devHub : (devHub = await this.getDevHubOrg());
660
+ if (!devHub) {
661
+ throw messages.createError('noDevHubFound');
662
+ }
663
+ if (devHub.getOrgId() === this.getOrgId()) {
664
+ // we're attempting to delete a DevHub
665
+ throw messages.createError('deleteOrgHubError');
666
+ }
667
+ try {
668
+ const devHubConn = devHub.getConnection();
669
+ const username = this.getUsername();
670
+ const activeScratchOrgRecordId = (await devHubConn.singleRecordQuery(`SELECT Id FROM ActiveScratchOrg WHERE SignupUsername='${username}'`)).Id;
671
+ this.logger.trace(`found matching ActiveScratchOrg with SignupUsername: ${username}. Deleting...`);
672
+ await this.destoryScratchOrg(devHub, activeScratchOrgRecordId);
673
+ await this.remove();
674
+ }
675
+ catch (err) {
676
+ this.logger.info(err instanceof Error ? err.message : err);
677
+ if (err instanceof Error && (err.name === 'INVALID_TYPE' || err.name === 'INSUFFICIENT_ACCESS_OR_READONLY')) {
678
+ // most likely from devHubConn.delete
679
+ this.logger.info('Insufficient privilege to access ActiveScratchOrgs.');
680
+ throw messages.createError('insufficientAccessToDelete');
681
+ }
682
+ if (err instanceof Error && err.name === connection_1.SingleRecordQueryErrors.NoRecords) {
683
+ // most likely from singleRecordQuery
684
+ this.logger.info('The above error can be the result of deleting an expired or already deleted org.');
685
+ this.logger.info('attempting to cleanup the auth file');
686
+ await this.removeAuth();
687
+ throw messages.createError('scratchOrgNotFound');
688
+ }
689
+ throw err;
690
+ }
691
+ }
519
692
  /**
520
693
  * Delete an auth info file from the local file system and any related cache information for
521
694
  * this Org. You don't want to call this method directly. Instead consider calling Org.remove()
@@ -548,7 +721,7 @@ class Org extends kit_1.AsyncOptionalCreatable {
548
721
  async retrieveSandboxOrgConfig() {
549
722
  return await sandboxOrgConfig_1.SandboxOrgConfig.create(sandboxOrgConfig_1.SandboxOrgConfig.getOptions(this.getOrgId()));
550
723
  }
551
- manageDelete(cb, dirPath, throwWhenRemoveFails) {
724
+ async manageDelete(cb, dirPath, throwWhenRemoveFails) {
552
725
  return cb().catch((e) => {
553
726
  if (throwWhenRemoveFails) {
554
727
  throw e;
@@ -610,6 +783,167 @@ class Org extends kit_1.AsyncOptionalCreatable {
610
783
  await this.manageDelete(async () => await sandboxOrgConfig.unlink(), sandboxOrgConfig.getPath(), throwWhenRemoveFails);
611
784
  }
612
785
  }
786
+ async writeSandboxAuthFile(sandboxProcessObj, sandboxRes) {
787
+ this.logger.debug('writeSandboxAuthFile sandboxProcessObj: %s, sandboxRes: %s', sandboxProcessObj, sandboxRes);
788
+ if (sandboxRes.authUserName) {
789
+ const productionAuthFields = this.connection.getAuthInfoFields();
790
+ this.logger.debug('Result from getAuthInfoFields: AuthFields %s', productionAuthFields);
791
+ // let's do headless auth via jwt (if we have privateKey) or web auth
792
+ const oauth2Options = {
793
+ loginUrl: sandboxRes.loginUrl,
794
+ instanceUrl: sandboxRes.instanceUrl,
795
+ username: sandboxRes.authUserName,
796
+ };
797
+ // If we don't have a privateKey then we assume it's web auth.
798
+ if (!productionAuthFields.privateKey) {
799
+ oauth2Options.redirectUri = `http://localhost:${await webOAuthServer_1.WebOAuthServer.determineOauthPort()}/OauthRedirect`;
800
+ oauth2Options.authCode = sandboxRes.authCode;
801
+ }
802
+ const authInfo = await authInfo_1.AuthInfo.create({
803
+ username: sandboxRes.authUserName,
804
+ oauth2Options,
805
+ parentUsername: productionAuthFields.username,
806
+ });
807
+ await authInfo.save();
808
+ const sandboxOrg = await Org.create({ aliasOrUsername: authInfo.getUsername() });
809
+ await sandboxOrg.setSandboxOrgConfigField(sandboxOrgConfig_1.SandboxOrgConfig.Fields.PROD_ORG_USERNAME,
810
+ // we couldn't get this far into the process without a production org so username will be there
811
+ productionAuthFields.username);
812
+ await lifecycleEvents_1.Lifecycle.getInstance().emit(SandboxEvents.EVENT_RESULT, {
813
+ sandboxProcessObj,
814
+ sandboxRes,
815
+ });
816
+ }
817
+ else {
818
+ // no authed sandbox user, error
819
+ throw messages.createError('missingAuthUsername', [sandboxProcessObj.SandboxName]);
820
+ }
821
+ }
822
+ /**
823
+ * Polls for the new sandbox to be created - and will write the associated auth files
824
+ *
825
+ * @private
826
+ * @param options
827
+ * sandboxProcessObj: The in-progress sandbox signup request
828
+ * retries: the number of retries to poll for every 30s
829
+ * shouldPoll: wait for polling, or just return
830
+ * pollInterval: Duration to sleep between poll events, default 30 seconds
831
+ */
832
+ async pollStatusAndAuth(options) {
833
+ const { sandboxProcessObj, retries, shouldPoll, pollInterval } = options;
834
+ this.logger.debug('PollStatusAndAuth called with SandboxProcessObject%s, retries %s', sandboxProcessObj, retries);
835
+ const lifecycle = lifecycleEvents_1.Lifecycle.getInstance();
836
+ let pollFinished = false;
837
+ let waitingOnAuth = false;
838
+ const sandboxInfo = await this.sandboxSignupComplete(sandboxProcessObj);
839
+ if (sandboxInfo) {
840
+ await lifecycleEvents_1.Lifecycle.getInstance().emit(SandboxEvents.EVENT_AUTH, sandboxInfo);
841
+ try {
842
+ this.logger.debug('sandbox signup complete with %s', sandboxInfo);
843
+ await this.writeSandboxAuthFile(sandboxProcessObj, sandboxInfo);
844
+ pollFinished = true;
845
+ }
846
+ catch (err) {
847
+ this.logger.debug('Exception while calling writeSandboxAuthFile %s', err);
848
+ if ((err === null || err === void 0 ? void 0 : err.name) === 'JWTAuthError' && (err === null || err === void 0 ? void 0 : err.stack.includes("user hasn't approved"))) {
849
+ waitingOnAuth = true;
850
+ }
851
+ else {
852
+ throw sfdxError_1.SfdxError.wrap(err);
853
+ }
854
+ }
855
+ }
856
+ if (!pollFinished) {
857
+ if (retries > 0) {
858
+ // emit the signup progress of the sandbox and query the production org again after waiting the interval
859
+ await Promise.all([
860
+ await lifecycle.emit(SandboxEvents.EVENT_STATUS, {
861
+ sandboxProcessObj,
862
+ interval: pollInterval.seconds,
863
+ retries,
864
+ waitingOnAuth,
865
+ }),
866
+ await kit_1.sleep(pollInterval),
867
+ ]);
868
+ const polledSandboxProcessObj = await this.querySandboxProcess(sandboxProcessObj.SandboxInfoId);
869
+ return this.pollStatusAndAuth({
870
+ sandboxProcessObj: polledSandboxProcessObj,
871
+ retries: retries - 1,
872
+ shouldPoll,
873
+ pollInterval,
874
+ });
875
+ }
876
+ else {
877
+ if (shouldPoll) {
878
+ // timed out on retries
879
+ throw messages.createError('orgPollingTimeout', [sandboxProcessObj.Status]);
880
+ }
881
+ else {
882
+ // The user didn't want us to poll, so simply return the status
883
+ // simply report status and exit
884
+ await lifecycle.emit(SandboxEvents.EVENT_ASYNC_RESULT, sandboxProcessObj);
885
+ }
886
+ }
887
+ }
888
+ return sandboxProcessObj;
889
+ }
890
+ /**
891
+ * query SandboxProcess via SandboxInfoId
892
+ *
893
+ * @param id SandboxInfoId to query for
894
+ * @private
895
+ */
896
+ async querySandboxProcess(id) {
897
+ const queryStr = `SELECT Id, Status, SandboxName, SandboxInfoId, LicenseType, CreatedDate, CopyProgress, SandboxOrganization, SourceId, Description, EndDate FROM SandboxProcess WHERE SandboxInfoId='${id}' AND Status != 'D'`;
898
+ return await this.connection.singleRecordQuery(queryStr, {
899
+ tooling: true,
900
+ });
901
+ }
902
+ /**
903
+ * determines if the sandbox has successfully been created
904
+ *
905
+ * @param sandboxProcessObj sandbox signup progeress
906
+ * @private
907
+ */
908
+ async sandboxSignupComplete(sandboxProcessObj) {
909
+ this.logger.debug('sandboxSignupComplete called with SandboxProcessObject %s', sandboxProcessObj);
910
+ if (!sandboxProcessObj.EndDate) {
911
+ return;
912
+ }
913
+ try {
914
+ // call server side /sandboxAuth API to auth the sandbox org user with the connected app
915
+ const authFields = this.connection.getAuthInfoFields();
916
+ const callbackUrl = `http://localhost:${await webOAuthServer_1.WebOAuthServer.determineOauthPort()}/OauthRedirect`;
917
+ const sandboxReq = {
918
+ // the sandbox signup has been completed on production, we have production clientId by this point
919
+ clientId: authFields.clientId,
920
+ sandboxName: sandboxProcessObj.SandboxName,
921
+ callbackUrl,
922
+ };
923
+ this.logger.debug('Calling sandboxAuth with SandboxUserAuthRequest %s', sandboxReq);
924
+ const url = `${this.connection.tooling._baseUrl()}/sandboxAuth`;
925
+ const params = {
926
+ method: 'POST',
927
+ url,
928
+ headers: { 'Content-Type': 'application/json' },
929
+ body: JSON.stringify(sandboxReq),
930
+ };
931
+ const result = await this.connection.tooling.request(params);
932
+ this.logger.debug('Result of calling sandboxAuth %s', result);
933
+ return result;
934
+ }
935
+ catch (err) {
936
+ // There are cases where the endDate is set before the sandbox has actually completed.
937
+ // In that case, the sandboxAuth call will throw a specific exception.
938
+ if ((err === null || err === void 0 ? void 0 : err.name) === 'INVALID_STATUS') {
939
+ this.logger.debug('Error while authenticating the user %s', err === null || err === void 0 ? void 0 : err.toString());
940
+ }
941
+ else {
942
+ // If it fails for any unexpected reason, just pass that through
943
+ throw sfdxError_1.SfdxError.wrap(err);
944
+ }
945
+ }
946
+ }
613
947
  }
614
948
  exports.Org = Org;
615
949
  (function (Org) {
@@ -50,7 +50,7 @@ export declare class SfdxError extends NamedError {
50
50
  * @param err The error to convert.
51
51
  */
52
52
  static wrap(err: Error | string): SfdxError;
53
- get code(): string;
53
+ get code(): string | undefined | any;
54
54
  set code(code: string);
55
55
  /**
56
56
  * Sets the context of the error. For convenience `this` object is returned.
package/lib/sfdxError.js CHANGED
@@ -65,6 +65,7 @@ class SfdxError extends kit_1.NamedError {
65
65
  }
66
66
  return sfdxError;
67
67
  }
68
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
68
69
  get code() {
69
70
  return this._code || this.name;
70
71
  }
@@ -1,4 +1,3 @@
1
- /// <reference types="sfdx-faye" />
2
1
  import { AsyncOptionalCreatable, Duration } from '@salesforce/kit';
3
2
  import { AnyJson } from '@salesforce/ts-types';
4
3
  import { Logger } from '../logger';
@@ -1,8 +1,8 @@
1
1
  import { AsyncOptionalCreatable, Duration, Env } from '@salesforce/kit/lib';
2
2
  import { AnyJson } from '@salesforce/ts-types/lib';
3
- import type { Client as CometClient, StreamProcessor } from 'sfdx-faye';
4
3
  import { Org } from '../org/org';
5
- export { Client as CometClient, Message, StreamProcessor, CometSubscription, StatusResult, StreamingExtension, } from 'sfdx-faye';
4
+ import { CometClient, CometSubscription, Message, StatusResult, StreamingExtension, StreamProcessor } from './types';
5
+ export { CometClient, CometSubscription, Message, StatusResult, StreamingExtension, StreamProcessor };
6
6
  /**
7
7
  * Inner streaming client interface. This implements the Cometd behavior.
8
8
  * Also allows for mocking the functional behavior.
@@ -187,7 +187,6 @@ export declare namespace StreamingClient {
187
187
  handshakeTimeout: Duration;
188
188
  channel: string;
189
189
  streamingImpl: StreamingClientIfc;
190
- private envDep;
191
190
  /**
192
191
  * Constructor for DefaultStreamingOptions
193
192
  *
@@ -11,12 +11,12 @@ exports.StreamingClient = exports.CometClient = void 0;
11
11
  const url_1 = require("url");
12
12
  const lib_1 = require("@salesforce/kit/lib");
13
13
  const lib_2 = require("@salesforce/ts-types/lib");
14
- const Faye = require("sfdx-faye");
14
+ const Faye = require("faye");
15
15
  const logger_1 = require("../logger");
16
16
  const sfdxError_1 = require("../sfdxError");
17
17
  const messages_1 = require("../messages");
18
- var sfdx_faye_1 = require("sfdx-faye");
19
- Object.defineProperty(exports, "CometClient", { enumerable: true, get: function () { return sfdx_faye_1.Client; } });
18
+ const types_1 = require("./types");
19
+ Object.defineProperty(exports, "CometClient", { enumerable: true, get: function () { return types_1.CometClient; } });
20
20
  messages_1.Messages.importMessagesDirectory(__dirname);
21
21
  const messages = messages_1.Messages.load('@salesforce/core', 'streaming', [
22
22
  'waitParamValidValueError',
@@ -337,6 +337,10 @@ exports.StreamingClient = StreamingClient;
337
337
  * @see {@link StatusResult}
338
338
  */
339
339
  constructor(org, channel, streamProcessor, envDep = lib_1.env) {
340
+ if (envDep) {
341
+ const logger = logger_1.Logger.childFromRoot('StreamingClient');
342
+ logger.warn('envDep is deprecated');
343
+ }
340
344
  if (!streamProcessor) {
341
345
  throw new sfdxError_1.SfdxError('Missing stream processor', 'MissingArg');
342
346
  }
@@ -346,7 +350,6 @@ exports.StreamingClient = StreamingClient;
346
350
  if (!channel) {
347
351
  throw new sfdxError_1.SfdxError('Missing streaming channel', 'MissingArg');
348
352
  }
349
- this.envDep = envDep;
350
353
  this.org = org;
351
354
  this.apiVersion = org.getConnection().getApiVersion();
352
355
  if (channel.startsWith('/system')) {
@@ -361,23 +364,14 @@ exports.StreamingClient = StreamingClient;
361
364
  this.handshakeTimeout = StreamingClient.DefaultOptions.DEFAULT_HANDSHAKE_TIMEOUT;
362
365
  this.streamingImpl = {
363
366
  getCometClient: (url) => {
364
- const x = this.envDep.getString(StreamingClient.DefaultOptions.SFDX_ENABLE_FAYE_COOKIES_ALLOW_ALL_PATHS);
365
- return new Faye.Client(url, {
366
- // This parameter ensures all cookies regardless of path are included in subsequent requests. Otherwise
367
- // only cookies with the path "/" and "/cometd" are known to be included.
368
- // if SFDX_ENABLE_FAYE_COOKIES_ALLOW_ALL_PATHS is *not* set the default to true.
369
- cookiesAllowAllPaths: x === undefined
370
- ? true
371
- : this.envDep.getBoolean(StreamingClient.DefaultOptions.SFDX_ENABLE_FAYE_COOKIES_ALLOW_ALL_PATHS),
372
- // WARNING - The allows request/response exchanges to be written to the log instance which includes
373
- // header and cookie information.
374
- enableRequestResponseLogging: this.envDep.getBoolean(StreamingClient.DefaultOptions.SFDX_ENABLE_FAYE_REQUEST_RESPONSE_LOGGING),
375
- });
367
+ // @ts-ignore
368
+ return new Faye.Client(url);
376
369
  },
377
370
  setLogger: (logLine) => {
378
371
  // @ts-ignore
379
372
  Faye.logger = {};
380
373
  ['info', 'error', 'fatal', 'warn', 'debug'].forEach((element) => {
374
+ // @ts-ignore
381
375
  lib_1.set(Faye.logger, element, logLine);
382
376
  });
383
377
  },
@@ -0,0 +1,89 @@
1
+ /// <reference types="node" />
2
+ import { EventEmitter } from 'events';
3
+ import { AnyFunction, AnyJson, JsonMap } from '@salesforce/ts-types';
4
+ export declare type Message = JsonMap;
5
+ export declare type Callback<T = unknown> = (...args: any[]) => T;
6
+ export interface StatusResult {
7
+ /**
8
+ * If the result of the streaming or polling client is expected to return a result
9
+ */
10
+ payload?: AnyJson;
11
+ /**
12
+ * Indicates to the streaming or polling client that the subscriber has what its needs. If `true` the client will end
13
+ * the messaging exchanges with the endpoint.
14
+ */
15
+ completed: boolean;
16
+ }
17
+ /**
18
+ * The subscription object returned from the cometd subscribe object.
19
+ */
20
+ export interface CometSubscription {
21
+ callback(callback: () => void): void;
22
+ errback(callback: (error: Error) => void): void;
23
+ }
24
+ /**
25
+ * Types for defining extensions.
26
+ */
27
+ export interface StreamingExtension {
28
+ /**
29
+ * Extension for outgoing message.
30
+ *
31
+ * @param message The message.
32
+ * @param callback The callback to invoke after the message is processed.
33
+ */
34
+ outgoing?: (message: JsonMap, callback: AnyFunction) => void;
35
+ /**
36
+ * Extension for the incoming message.
37
+ *
38
+ * @param message The message.
39
+ * @param callback The callback to invoke after the message is processed.
40
+ */
41
+ incoming?: (message: JsonMap, callback: AnyFunction) => void;
42
+ }
43
+ /**
44
+ * Function type for processing messages
45
+ */
46
+ export declare type StreamProcessor = (message: JsonMap) => StatusResult;
47
+ /**
48
+ * Comet client interface. The is to allow for mocking the inner streaming Cometd implementation.
49
+ * The Faye implementation is used by default but it could be used to adapt another Cometd impl.
50
+ */
51
+ export declare abstract class CometClient extends EventEmitter {
52
+ /**
53
+ * Disable polling features.
54
+ *
55
+ * @param label Polling feature label.
56
+ */
57
+ abstract disable(label: string): void;
58
+ /**
59
+ * Add a custom extension to the underlying client.
60
+ *
61
+ * @param extension The json function for the extension.
62
+ */
63
+ abstract addExtension(extension: StreamingExtension): void;
64
+ /**
65
+ * Sets an http header name/value.
66
+ *
67
+ * @param name The header name.
68
+ * @param value The header value.
69
+ */
70
+ abstract setHeader(name: string, value: string): void;
71
+ /**
72
+ * handshake with the streaming channel
73
+ *
74
+ * @param callback Callback for the handshake when it successfully completes. The handshake should throw
75
+ * errors when errors are encountered.
76
+ */
77
+ abstract handshake(callback: () => void): void;
78
+ /**
79
+ * Subscribes to Comet topics. Subscribe should perform a handshake if one hasn't been performed yet.
80
+ *
81
+ * @param channel The topic to subscribe to.
82
+ * @param callback The callback to execute once a message has been received.
83
+ */
84
+ abstract subscribe(channel: string, callback: (message: JsonMap) => void): CometSubscription;
85
+ /**
86
+ * Method to call to disconnect the client from the server.
87
+ */
88
+ abstract disconnect(): void;
89
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CometClient = void 0;
4
+ /*
5
+ * Copyright (c) 2020, salesforce.com, inc.
6
+ * All rights reserved.
7
+ * Licensed under the BSD 3-Clause license.
8
+ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
9
+ */
10
+ const events_1 = require("events");
11
+ /**
12
+ * Comet client interface. The is to allow for mocking the inner streaming Cometd implementation.
13
+ * The Faye implementation is used by default but it could be used to adapt another Cometd impl.
14
+ */
15
+ class CometClient extends events_1.EventEmitter {
16
+ }
17
+ exports.CometClient = CometClient;
18
+ //# sourceMappingURL=types.js.map