Skip to content

Commit

Permalink
fix(setGlobalConfig): merge multiple levels deep
Browse files Browse the repository at this point in the history
Merges config multiple levels deep. Also fixes docs and tests.
  • Loading branch information
advaiyalad committed Apr 23, 2021
1 parent 314ca1f commit b8cdd1d
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 7 deletions.
8 changes: 5 additions & 3 deletions docs/other/setGlobalConfig.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# setGlobalConfig

This util function sets global config options, merging (1 level deep only) with the defaults. These options are then the defaults used for every request. It is the **recommended** way of setting global config. Setting global config directly is not recommended.
This util function sets global config options, merging with the defaults. These options are then the defaults used for every request. It is the **recommended** way of setting global config. Setting global config directly is not recommended.

## Usage:

Expand All @@ -16,14 +16,16 @@ yahooFinance.setGlobalConfig({

Notes:

- Options are merged only one level deep:
- Config provided to this function is validated.

- Options are merged infinite levels deep:
```js
import yahooFinance from 'yahoo-finance2';

yahooFinance.setGlobalConfig({
queue: {
concurrency: 2,
// timeout not set anymore, may/will cause errors
// timeout is still set
}
});
```
23 changes: 21 additions & 2 deletions src/lib/setGlobalConfig.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
import testYf from "../../tests/testYf";
import options from "./options";
import setGlobalConfig from "./setGlobalConfig";
const yf = testYf({ setGlobalConfig });

describe("setGlobalConfig", () => {
it("sets config options", () => {
const optionsBackup = JSON.parse(JSON.stringify(options));
beforeEach(() => {
yf._opts = JSON.parse(JSON.stringify(optionsBackup));
});

it("sets config options and passes validation", () => {
const configOverrides = { queue: { concurrency: 10, timeout: 90 } };
yf.setGlobalConfig(configOverrides);
expect(yf._opts.queue).toEqual(configOverrides.queue);
expect(yf._opts).toEqual({ ...optionsBackup, ...configOverrides });
});
it("sets config options multiple levels deep", () => {
const configOverrides = { queue: { concurrency: 10 } };
yf.setGlobalConfig(configOverrides);
expect(yf._opts.queue).toEqual({
concurrency: 10,
timeout: optionsBackup.queue.timeout,
});
});
it("should throw on invalid config", () => {
expect(() => yf.setGlobalConfig({ queue: { abc: "" } })).toThrow(
/yahooFinance.setGlobalConfig called with invalid options\./
);
});
});
21 changes: 19 additions & 2 deletions src/lib/setGlobalConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,24 @@ export default function setGlobalConfig(
options: this._opts.validation,
schemaKey: "#/definitions/PartialOptions",
});
for (const key of Reflect.ownKeys(config)) {
this._opts[key] = config[key as keyof Options];
mergeObjects(this._opts, config as Obj);
}

type Obj = Record<string, string | ObjRecurse>;

// This is fine, since this is just a hack for recursive types
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface ObjRecurse extends Obj {}

function mergeObjects(original: Obj, objToMerge: Obj) {
const ownKeys: (keyof typeof objToMerge)[] = Reflect.ownKeys(
objToMerge
) as string[];
for (const key of ownKeys) {
if (typeof objToMerge[key] === "object") {
mergeObjects(original[key] as Obj, objToMerge[key] as Obj);
} else {
original[key] = objToMerge[key];
}
}
}

0 comments on commit b8cdd1d

Please sign in to comment.