Skip to content

Commit

Permalink
fix: correct typings for configStore get
Browse files Browse the repository at this point in the history
  • Loading branch information
mshanemc committed Jan 24, 2024
1 parent 92acff2 commit 4dad8c7
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 25 deletions.
10 changes: 5 additions & 5 deletions src/config/configStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import { ConfigContents, ConfigEntry, ConfigValue, Key } from './configStackType
export interface ConfigStore<P extends ConfigContents = ConfigContents> {
// Map manipulation methods
entries(): ConfigEntry[];
get<K extends Key<P>>(key: K, decrypt: boolean): P[K];
get<T extends ConfigValue>(key: string, decrypt: boolean): T;
get<K extends Key<P>>(key: K, decrypt: boolean): P[K] | undefined;
get<T extends ConfigValue>(key: string, decrypt: boolean): T | undefined;
getKeysByValue(value: ConfigValue): Array<Key<P>>;
has(key: string): boolean;
keys(): Array<Key<P>>;
Expand Down Expand Up @@ -88,9 +88,9 @@ export abstract class BaseConfigStore<
* @param decrypt If it is an encrypted key, decrypt the value.
* If the value is an object, a clone will be returned.
*/
public get<K extends Key<P>>(key: K, decrypt?: boolean): P[K];
public get<V = ConfigValue>(key: string, decrypt?: boolean): V;
public get<K extends Key<P>>(key: K | string, decrypt = false): P[K] | ConfigValue {
public get<K extends Key<P>>(key: K, decrypt?: boolean): P[K] | undefined;
public get<V = ConfigValue>(key: string, decrypt?: boolean): V | undefined;
public get<K extends Key<P>>(key: K | string, decrypt = false): P[K] | ConfigValue | undefined {
const rawValue = this.contents.get(key as K);

if (this.hasEncryption() && decrypt) {
Expand Down
7 changes: 5 additions & 2 deletions src/org/scratchOrgCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,12 @@ export const scratchOrgResume = async (jobId: string): Promise<ScratchOrgCreateR
emit({ stage: 'send request' }),
]);
logger.debug(`resuming scratch org creation for jobId: ${jobId}`);
if (!cache.has(jobId)) {
const cached = cache.get(jobId);

if (!cached) {
throw messages.createError('CacheMissError', [jobId]);
}

const {
hubUsername,
apiVersion,
Expand All @@ -122,7 +125,7 @@ export const scratchOrgResume = async (jobId: string): Promise<ScratchOrgCreateR
alias,
setDefault,
tracksSource,
} = cache.get(jobId);
} = cached;

const hubOrg = await Org.create({ aliasOrUsername: hubUsername });
const soi = await queryScratchOrgInfo(hubOrg, jobId);
Expand Down
38 changes: 22 additions & 16 deletions test/unit/config/configStoreTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* Licensed under the BSD 3-Clause license.
* For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
*/
import { expect } from 'chai';
import { expect, assert } from 'chai';
import { AuthInfoConfig } from '../../../src/config/authInfoConfig';
import { BaseConfigStore } from '../../../src/config/configStore';
import { ConfigContents } from '../../../src/config/configStackTypes';
Expand Down Expand Up @@ -53,9 +53,9 @@ describe('ConfigStore', () => {
const config = new TestConfig<{ '1': { a: string } }>();
config.set('1', { a: 'a' });

config.get('1').a = 'b';
config.get('1')!.a = 'b';

expect(config.get('1').a).to.equal('b');
expect(config.get('1')!.a).to.equal('b');
});

it('updates the object reference', async () => {
Expand All @@ -64,8 +64,13 @@ describe('ConfigStore', () => {

config.update('1', { b: 'c' });

expect(config.get('1').a).to.equal('a');
expect(config.get('1').b).to.equal('c');
expect(config.get('1')!.a).to.equal('a');
expect(config.get('1')!.b).to.equal('c');
});

it('undefined keys return undefined', async () => {
const config = new TestConfig<{ '1': { a: string } }>();
expect(config.get('not-a-thing')).to.equal(undefined);
});

describe('encryption', () => {
Expand Down Expand Up @@ -111,9 +116,9 @@ describe('ConfigStore', () => {
});
const owner = config.get('owner');
// encrypted
expect(owner.creditCardNumber).to.not.equal(expected);
expect(owner?.creditCardNumber).to.not.equal(expected);
// decrypted
expect(config.get('owner', true).creditCardNumber).to.equal(expected);
expect(config.get('owner', true)?.creditCardNumber).to.equal(expected);
});

it('encrypts nested key using regexp', async () => {
Expand All @@ -129,9 +134,9 @@ describe('ConfigStore', () => {
});
const owner = config.get('owner');
// encrypted
expect(owner.superPassword).to.not.equal(expected);
expect(owner?.superPassword).to.not.equal(expected);
// decrypted
expect(config.get('owner', true).superPassword).to.equal(expected);
expect(config.get('owner', true)?.superPassword).to.equal(expected);
});

it('decrypt returns copies', async () => {
Expand All @@ -142,11 +147,12 @@ describe('ConfigStore', () => {
config.set('owner', owner);

const decryptedOwner = config.get('owner', true);
assert(decryptedOwner);
// Because we retrieved an decrypted object on a config with encryption,
// it should return a clone so it doesn't accidentally save decrypted data.
decryptedOwner.creditCardNumber = 'invalid';
expect(config.get('owner').creditCardNumber).to.not.equal('invalid');
expect(config.get('owner', true).creditCardNumber).to.equal(expected);
expect(config.get('owner')?.creditCardNumber).to.not.equal('invalid');
expect(config.get('owner', true)?.creditCardNumber).to.equal(expected);
});

// Ensures accessToken and refreshToken are both decrypted upon config.get()
Expand All @@ -170,13 +176,13 @@ describe('ConfigStore', () => {
const owner = { name: 'Bob', creditCardNumber: expected };
// @ts-expect-error incomplete owner
config.set('owner', owner);
const encryptedCreditCardNumber = config.get('owner').creditCardNumber;
const encryptedCreditCardNumber = config.get('owner')?.creditCardNumber;
const contents = config.getContents();
contents.owner.name = 'Tim';
// @ts-expect-error private method
config.setContents(contents);
expect(config.get('owner').name).to.equal(contents.owner.name);
expect(config.get('owner').creditCardNumber).to.equal(encryptedCreditCardNumber);
expect(config.get('owner')?.name).to.equal(contents.owner.name);
expect(config.get('owner')?.creditCardNumber).to.equal(encryptedCreditCardNumber);
});

it('updates encrypted object', async () => {
Expand All @@ -188,8 +194,8 @@ describe('ConfigStore', () => {

config.update('owner', { creditCardNumber: expected });

expect(config.get('owner').name).to.equal(owner.name);
expect(config.get('owner', true).creditCardNumber).to.equal(expected);
expect(config.get('owner')?.name).to.equal(owner.name);
expect(config.get('owner', true)?.creditCardNumber).to.equal(expected);
});
});
});
4 changes: 2 additions & 2 deletions test/unit/config/ttlConfigTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ describe('TTLConfig', () => {
it('should return true if timestamp is older than TTL', async () => {
const config = await TestConfig.create();
config.set('1', { one: 'one' });
const isExpired = config.isExpired(new Date().getTime() + Duration.days(7).milliseconds, config.get('1'));
const isExpired = config.isExpired(new Date().getTime() + Duration.days(7).milliseconds, config.get('1')!);
expect(isExpired).to.be.true;
});

it('should return false if timestamp is not older than TTL', async () => {
const config = await TestConfig.create();
config.set('1', { one: 'one' });
const isExpired = config.isExpired(new Date().getTime(), config.get('1'));
const isExpired = config.isExpired(new Date().getTime(), config.get('1')!);
expect(isExpired).to.be.false;
});
});
Expand Down

2 comments on commit 4dad8c7

@svc-cli-bot
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logger Benchmarks - ubuntu-latest

Benchmark suite Current: 4dad8c7 Previous: b0ae322 Ratio
Child logger creation 464655 ops/sec (±2.43%) 473843 ops/sec (±1.42%) 1.02
Logging a string on root logger 727812 ops/sec (±7.60%) 869547 ops/sec (±10.43%) 1.19
Logging an object on root logger 607337 ops/sec (±8.34%) 595363 ops/sec (±7.94%) 0.98
Logging an object with a message on root logger 8341 ops/sec (±204.87%) 5318 ops/sec (±223.62%) 0.64
Logging an object with a redacted prop on root logger 444544 ops/sec (±6.75%) 406691 ops/sec (±15.56%) 0.91
Logging a nested 3-level object on root logger 353721 ops/sec (±7.60%) 353970 ops/sec (±8.72%) 1.00

This comment was automatically generated by workflow using github-action-benchmark.

@svc-cli-bot
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logger Benchmarks - windows-latest

Benchmark suite Current: 4dad8c7 Previous: b0ae322 Ratio
Child logger creation 338956 ops/sec (±0.43%) 317663 ops/sec (±1.57%) 0.94
Logging a string on root logger 820024 ops/sec (±10.06%) 781351 ops/sec (±8.56%) 0.95
Logging an object on root logger 592522 ops/sec (±8.99%) 591511 ops/sec (±4.84%) 1.00
Logging an object with a message on root logger 7361 ops/sec (±203.74%) 8379 ops/sec (±199.62%) 1.14
Logging an object with a redacted prop on root logger 466039 ops/sec (±6.85%) 428204 ops/sec (±11.17%) 0.92
Logging a nested 3-level object on root logger 315877 ops/sec (±10.77%) 344821 ops/sec (±5.10%) 1.09

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.