Skip to content

Commit

Permalink
fix: lifecycle should be a singleton across core versions
Browse files Browse the repository at this point in the history
  • Loading branch information
amphro committed Oct 1, 2020
1 parent 9b63445 commit 66a450b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 39 deletions.
18 changes: 14 additions & 4 deletions src/lifecycleEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import * as Debug from 'debug';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type callback = (data: any) => Promise<void>;

declare const global: {
salesforceCoreLifecycle?: Lifecycle;
};

/**
* An asynchronous event listener and emitter that follows the singleton pattern. The singleton pattern allows lifecycle
* events to be emitted from deep within a library and still be consumed by any other library or tool. It allows other
Expand All @@ -31,7 +35,6 @@ type callback = (data: any) => Promise<void>;
* ```
*/
export class Lifecycle {
private static instance: Lifecycle;
private debug = Debug(`sfdx:${this.constructor.name}`);
private readonly listeners: Dictionary<callback[]>;

Expand All @@ -42,10 +45,17 @@ export class Lifecycle {
* Retrieve the singleton instance of this class so that all listeners and emitters can interact from any library or tool
*/
public static getInstance(): Lifecycle {
if (!this.instance) {
this.instance = new Lifecycle();
// Across a npm dependency tree, there may be a LOT of versions of @salesforce/core. We want to ensure that consumers are notified when
// listening on a lifecycle event that is fired by a different version of @salesforce/core. Adding the instance on the global object will
// ensure this. Note: There needs to be version checking up update lifecycle to the newer version if ANYTHING is ever added to this class.
// One way this can be done by adding a version = require(../package.json).version to the Lifecycle class, then checking that here.
// For example, if instance is created with @salesforce/core@2.12.2 and something is added in 2.14.0, someone who depends on version 2.14.0
// may get an instance that was created with 2.12.2.
// Nothing should EVER be removed, even across major versions.
if (!global.salesforceCoreLifecycle) {
global.salesforceCoreLifecycle = new Lifecycle();
}
return this.instance;
return global.salesforceCoreLifecycle;
}

/**
Expand Down
14 changes: 13 additions & 1 deletion test/unit/lifecycleEventsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,19 @@ describe('lifecycleEvents', () => {
chai.assert(Lifecycle.getInstance() === Lifecycle.getInstance());
});

it('succsssful event registration and emitting causes the callback to be called', async () => {
it('getInstance is on the global object to protect against npm version dependency mismatch', async () => {
// @ts-ignore don't declare the type in the test
chai.assert(Lifecycle.getInstance() === global.salesforceCoreLifecycle);
});

it('has not changed', async () => {
chai.assert(
Object.getOwnPropertyNames(Lifecycle.prototype).length === 5,
'Lifecycle can not be changed without adding version support to update the instance to the latest version. See note in Lifecycle.getInstance'
);
});

it('successful event registration and emitting causes the callback to be called', async () => {
Lifecycle.getInstance().on('test1', async (result) => {
fake.bar('test1', result);
});
Expand Down
36 changes: 2 additions & 34 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2066,7 +2066,7 @@ debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
dependencies:
ms "2.0.0"

debuglog@*, debuglog@^1.0.1:
debuglog@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"
integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=
Expand Down Expand Up @@ -3613,7 +3613,7 @@ import-lazy@^2.1.0:
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=

imurmurhash@*, imurmurhash@^0.1.4:
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
Expand Down Expand Up @@ -4541,11 +4541,6 @@ lockfile@^1.0.4:
dependencies:
signal-exit "^3.0.2"

lodash._baseindexof@*:
version "3.1.0"
resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"
integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=

lodash._baseuniq@~4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
Expand All @@ -4554,33 +4549,11 @@ lodash._baseuniq@~4.6.0:
lodash._createset "~4.0.0"
lodash._root "~3.0.0"

lodash._bindcallback@*:
version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"
integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4=

lodash._cacheindexof@*:
version "3.0.2"
resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"
integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=

lodash._createcache@*:
version "3.1.2"
resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=
dependencies:
lodash._getnative "^3.0.0"

lodash._createset@~4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"
integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=

lodash._getnative@*, lodash._getnative@^3.0.0:
version "3.9.1"
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"
integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=

lodash._reinterpolate@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
Expand Down Expand Up @@ -4661,11 +4634,6 @@ lodash.once@^4.0.0:
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=

lodash.restparam@*:
version "3.6.1"
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"
integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=

lodash.set@^4.3.2:
version "4.3.2"
resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23"
Expand Down

0 comments on commit 66a450b

Please sign in to comment.