From d71ac1f877a9ad7c42f4f80f6fe642e0b68c1437 Mon Sep 17 00:00:00 2001 From: Ronan-Yann Lorin Date: Sat, 16 Sep 2023 22:39:33 +0200 Subject: [PATCH 1/3] subscription.endEventReceived implementation begin --- .eslintrc => .eslintrc.json | 18 +- package.json | 10 +- src/api-next/api-next.ts | 89 ++- src/core/api-next/subscription.ts | 40 +- src/core/io/controller.ts | 10 + src/core/io/socket.ts | 8 +- src/tests/unit/api-next/get-positions.test.ts | 4 +- src/tests/unit/api/order/placeOrder.test.ts | 6 +- src/tools/account-summary.ts | 5 +- src/tools/commission-reports.ts | 5 +- src/tools/common/ib-api-next-app.ts | 11 +- src/tools/contract-details.ts | 6 +- src/tools/current-time.ts | 6 +- src/tools/execution-details.ts | 5 +- src/tools/get-head-timestamp.ts | 6 +- src/tools/histogram-data.ts | 5 +- src/tools/historical-data-updates.ts | 5 +- src/tools/historical-data.ts | 5 +- src/tools/historical-ticks-bid-ask.ts | 5 +- src/tools/historical-ticks-last.ts | 5 +- src/tools/historical-ticks-mid.ts | 5 +- src/tools/managed-accts.ts | 6 +- src/tools/market-data-snapshot.ts | 13 +- src/tools/market-data.ts | 13 +- src/tools/market-depth-exchanges.ts | 6 +- src/tools/market-depth.ts | 5 +- src/tools/market-scanner.ts | 5 +- src/tools/modify-order.ts | 6 +- src/tools/next-valid-order-id.ts | 6 +- src/tools/open-orders-auto.ts | 5 +- src/tools/open-orders.ts | 6 +- src/tools/place-new-order.ts | 6 +- src/tools/place-order.ts | 3 +- src/tools/pnl-single.ts | 5 +- src/tools/pnl.ts | 5 +- src/tools/positions.ts | 5 +- src/tools/search-contracts.ts | 5 +- src/tools/sec-def-opt-params.ts | 6 +- src/tools/user-info.ts | 6 +- yarn.lock | 678 ++++++++++-------- 40 files changed, 547 insertions(+), 502 deletions(-) rename .eslintrc => .eslintrc.json (95%) diff --git a/.eslintrc b/.eslintrc.json similarity index 95% rename from .eslintrc rename to .eslintrc.json index abb8b5a7..95d9c21f 100644 --- a/.eslintrc +++ b/.eslintrc.json @@ -1,19 +1,17 @@ { - "root": true, - "parser": "@typescript-eslint/parser", - "plugins": ["@typescript-eslint", "rxjs"], "extends": ["plugin:@typescript-eslint/recommended"], + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": 2020, "project": ["tsconfig.json"], "sourceType": "module" }, + "plugins": ["@typescript-eslint", "rxjs"], + "root": true, "rules": { - "strict": "error", - "semi": ["error", "always"], - "quotes": ["error", "double"], "@typescript-eslint/explicit-function-return-type": "off", "@typescript-eslint/explicit-module-boundary-types": "off", + "@typescript-eslint/no-duplicate-enum-values": "error", "@typescript-eslint/no-explicit-any": 1, "@typescript-eslint/no-inferrable-types": [ "warn", @@ -21,6 +19,7 @@ "ignoreParameters": true } ], + "@typescript-eslint/no-unsafe-declaration-merging": "error", "@typescript-eslint/no-unused-vars": [ "warn", { @@ -29,12 +28,13 @@ "varsIgnorePattern": "^_" } ], - "@typescript-eslint/no-duplicate-enum-values": "error", - "@typescript-eslint/no-unsafe-declaration-merging": "error", + "quotes": ["error", "double"], "rxjs/no-async-subscribe": "error", "rxjs/no-ignored-observable": "error", "rxjs/no-ignored-subscription": "error", "rxjs/no-unbound-methods": "error", - "rxjs/throw-error": "error" + "rxjs/throw-error": "error", + "semi": ["error", "always"], + "strict": "error" } } diff --git a/package.json b/package.json index c3183015..627ca4ac 100644 --- a/package.json +++ b/package.json @@ -77,18 +77,18 @@ "@types/jest": "^29.5.4", "@types/node": "^18.17.15", "@types/source-map-support": "^0.5.7", - "@typescript-eslint/eslint-plugin": "^6.6.0", - "@typescript-eslint/parser": "^6.6.0", + "@typescript-eslint/eslint-plugin": "^6.7.0", + "@typescript-eslint/parser": "^6.7.0", "ajv": "^8.12.0", "eslint": "^8.49.0", "eslint-plugin-jest": "^27.2.3", "eslint-plugin-rxjs": "^5.0.3", - "jest": "^29.6.4", - "jest-environment-node": "^29.6.4", + "jest": "^29.7.0", + "jest-environment-node": "^29.7.0", "jest-junit": "^16.0.0", "ts-jest": "^29.1.1", "typedoc": "^0.25.1", - "typescript": "^4.9.5" + "typescript": "^5.2.2" }, "engines": { "node": ">=18.0.0" diff --git a/src/api-next/api-next.ts b/src/api-next/api-next.ts index 2a64e59b..bda26c31 100644 --- a/src/api-next/api-next.ts +++ b/src/api-next/api-next.ts @@ -784,7 +784,9 @@ export class IBApiNext { } } - if (hasAdded) { + if (!subscription.endEventReceived) { + subscription.lastAllValue = cached; + } else if (hasAdded) { subscription.next({ all: cached, added: new MutableAccountPositions([[account, [updatedPosition]]]), @@ -803,6 +805,19 @@ export class IBApiNext { }); }; + /** position end enumeration event handler */ + private readonly onPositionEnd = ( + subscriptions: Map>, + ): void => { + // notify all subscribers + subscriptions.forEach((subscription) => { + const lastAllValue = + subscription.lastAllValue ?? new MutableAccountPositions(); + subscription.endEventReceived = true; + subscription.next({ all: lastAllValue }); + }); + }; + /** * Create subscription to receive the positions on all accessible accounts. */ @@ -814,7 +829,10 @@ export class IBApiNext { () => { this.api.cancelPositions(); }, - [[EventName.position, this.onPosition]], + [ + [EventName.position, this.onPosition], + [EventName.positionEnd, this.onPositionEnd], + ], "getPositions", ); } @@ -2363,28 +2381,26 @@ export class IBApiNext { // console.log("onScannerData", item); - const lastValue = subscription.lastValue ?? { - all: new Map(), - allset: false, - }; + const lastAllValue = + subscription.lastAllValue ?? + new Map(); - const existing = lastValue.all.get(rank) != undefined; - lastValue.all.set(rank, item); - if (lastValue.allset) { + const existing = lastAllValue.get(rank) != undefined; + lastAllValue.set(rank, item); + if (subscription.endEventReceived) { const updated: MarketScannerRows = new Map< MarketScannerItemRank, MarketScannerItem >(); updated.set(rank, item); subscription.next({ - all: lastValue.all, - allset: lastValue.allset, + all: lastAllValue, changed: existing ? updated : undefined, added: existing ? undefined : updated, }); } else { // console.log("saving for future use", lastValue); - subscription.lastValue = lastValue; + subscription.lastAllValue = lastAllValue; } }; @@ -2403,14 +2419,13 @@ export class IBApiNext { return; } - const lastValue = subscription.lastValue ?? { - all: new Map(), - }; + const lastAllValue = + subscription.lastAllValue ?? + new Map(); const updated: IBApiNextItemListUpdate = { - all: lastValue.all, - allset: true, - added: lastValue.all, + all: lastAllValue, }; + subscription.endEventReceived = true; // console.log("onScannerDataEnd", updated); @@ -2539,10 +2554,14 @@ export class IBApiNext { orderStatus: undefined, }; allOrders.push(addedOrder); - sub.next({ - all: allOrders, - added: [addedOrder], - }); + if (sub.endEventReceived) { + sub.next({ + all: allOrders, + added: [addedOrder], + }); + } else { + sub.lastAllValue = allOrders; + } } else { // update const updatedOrder: OpenOrder = allOrders[changeOrderIndex]; @@ -2564,13 +2583,16 @@ export class IBApiNext { }; /** - * Ends the subscrition once all openOrders are recieved + * Ends the subscription once all openOrders are recieved * @param subscriptions: listeners */ - private readonly onOpenOrderEnd = ( + private readonly onOpenOrderComplete = ( subscriptions: Map>, ): void => { subscriptions.forEach((sub) => { + const allOrders = sub.lastAllValue ?? []; + sub.endEventReceived = true; + sub.next({ all: allOrders }); sub.complete(); }); }; @@ -2675,6 +2697,21 @@ export class IBApiNext { }); }; + /** + * Ends the subscription once all openOrders are recieved + * @param subscriptions: listeners + */ + private readonly onOpenOrderEnd = ( + subscriptions: Map>, + ): void => { + // notify all subscribers + subscriptions.forEach((subscription) => { + const lastAllValue = subscription.lastAllValue ?? []; + subscription.endEventReceived = true; + subscription.next({ all: lastAllValue }); + }); + }; + /** * Requests all current open orders in associated accounts at the current moment. */ @@ -2690,7 +2727,7 @@ export class IBApiNext { [EventName.openOrder, this.onOpenOrder], [EventName.orderStatus, this.onOrderStatus], [EventName.orderBound, this.onOrderBound], - [EventName.openOrderEnd, this.onOpenOrderEnd], + [EventName.openOrderEnd, this.onOpenOrderComplete], ], "getAllOpenOrders", // use same instance id each time, to make sure there is only 1 pending request at time ) @@ -2715,6 +2752,7 @@ export class IBApiNext { [EventName.openOrder, this.onOpenOrder], [EventName.orderStatus, this.onOrderStatus], [EventName.orderBound, this.onOrderBound], + [EventName.openOrderEnd, this.onOpenOrderEnd], ], "getOpenOrders", // use same instance id each time, to make sure there is only 1 pending request at time ); @@ -2738,6 +2776,7 @@ export class IBApiNext { [EventName.openOrder, this.onOpenOrder], [EventName.orderStatus, this.onOrderStatus], [EventName.orderBound, this.onOrderBound], + [EventName.openOrderEnd, this.onOpenOrderEnd], ], "getAutoOpenOrders", // use same instance id each time, to make sure there is only 1 pending request at time ); diff --git a/src/core/api-next/subscription.ts b/src/core/api-next/subscription.ts index 4b3029d7..7154bd50 100644 --- a/src/core/api-next/subscription.ts +++ b/src/core/api-next/subscription.ts @@ -47,28 +47,36 @@ export class IBApiNextSubscription { /** The replay subject, holding the latest emitted values. */ private subject = new ReplaySubject>(1); + /** To prepare RxJS v8 that will remove subject.hasError */ + private hasError = false; + /** The last 'all' value as send to subscribers. */ - private _lastValue?: IBApiNextItemListUpdateMinimal; + private _lastAllValue?: T; /** The [[Subscription]] on the connection state. */ private connectionState$?: Subscription; /** true when the end-event on an enumeration request has been received, false otherwise. */ - // public endEventReceived = false; // TODO: unused? + private _endEventReceived = false; /** Get the last 'all' value as send to subscribers. */ get lastAllValue(): T | undefined { - return this._lastValue?.all; + return this._lastAllValue; + } + + /** @internal Set the last 'all' value without publishing it to subscribers. For internal use only. */ + set lastAllValue(value: T) { + this._lastAllValue = value; } - /** Get the last value as previouly saved or send to subscribers. */ - get lastValue(): IBApiNextItemListUpdateMinimal | undefined { - return this._lastValue; + /** @internal Get the end event flag. For internal use only. */ + get endEventReceived(): boolean { + return this._endEventReceived; } - /** Set the last value without publishing it to subscribers. For internal use only. */ - set lastValue(value: IBApiNextItemListUpdateMinimal) { - this._lastValue = { all: value.all, allset: value.allset }; + /** @internal Set the end event flag seen. For internal use only. */ + set endEventReceived(value: boolean) { + this._endEventReceived = value; } /** @@ -77,7 +85,7 @@ export class IBApiNextSubscription { * @param value: The next value. */ next(value: IBApiNextItemListUpdate): void { - this._lastValue = { all: value.all, allset: value.allset }; + this._lastAllValue = value.all; this.subject.next(value); } @@ -93,7 +101,9 @@ export class IBApiNextSubscription { * @param error: The [[IBApiError]] object. */ error(error: IBApiNextError): void { - delete this._lastValue; + delete this._lastAllValue; + this._endEventReceived = false; + this.hasError = true; this.subject.error(error); this.cancelTwsSubscription(); } @@ -106,7 +116,8 @@ export class IBApiNextSubscription { return new Observable>((subscriber) => { // create new subject and reqId if there is an has error - if (this.subject.hasError) { + if (this.hasError) { + this.hasError = false; this.subject = new ReplaySubject(1); this.reqId = this.api.nextReqId; } @@ -120,7 +131,6 @@ export class IBApiNextSubscription { ? ({ all: val.all, added: val.all, - allset: val.allset, } as ItemListUpdate) : val; }), @@ -155,8 +165,8 @@ export class IBApiNextSubscription { if (!this.connectionState$) { this.connectionState$ = this.api.connectionState.subscribe((state) => { if (state === ConnectionState.Connected) { - delete this._lastValue; - // this.endEventReceived = false; + delete this._lastAllValue; + this.endEventReceived = false; this.requestFunction(); } }); diff --git a/src/core/io/controller.ts b/src/core/io/controller.ts index 2e82f5ca..8473c388 100644 --- a/src/core/io/controller.ts +++ b/src/core/io/controller.ts @@ -181,6 +181,16 @@ export class Controller implements EncoderCallbacks, DecoderCallbacks { } this.ib.emit(EventName.all, eventName, args); + + /* + Important: The IBApi.EWrapper.nextValidID callback is commonly used to indicate that the connection is completed + and other messages can be sent from the API client to TWS. + There is the possibility that function calls made prior to this time could be dropped by TWS. + */ + if (eventName === EventName.nextValidId) { + // console.log("nextValidId received"); + this.resume(); + } } /** diff --git a/src/core/io/socket.ts b/src/core/io/socket.ts index f7eaa5f7..9753a7df 100644 --- a/src/core/io/socket.ts +++ b/src/core/io/socket.ts @@ -382,10 +382,10 @@ export class Socket { } } - // resume controller after CONNECT_DELAY, fix connect issue - setTimeout(() => { - this.controller.resume(); - }, CONNECT_DELAY); + // resume controller moved to crontroller + // setTimeout(() => { + // this.controller.resume(); + // }, CONNECT_DELAY); } /** diff --git a/src/tests/unit/api-next/get-positions.test.ts b/src/tests/unit/api-next/get-positions.test.ts index 26ac96ce..d808925a 100644 --- a/src/tests/unit/api-next/get-positions.test.ts +++ b/src/tests/unit/api-next/get-positions.test.ts @@ -57,6 +57,7 @@ describe("RxJS Wrapper: getPositions()", () => { }); api.emit(EventName.position, accountId, positionContract, posSize, avgCost); + api.emit(EventName.positionEnd); }); test("Detected added / changed / removed", (done) => { @@ -107,7 +108,7 @@ describe("RxJS Wrapper: getPositions()", () => { posSize1, avgCost, ); - + api.emit(EventName.positionEnd); api.emit( EventName.position, accountId, @@ -161,5 +162,6 @@ describe("RxJS Wrapper: getPositions()", () => { }); api.emit(EventName.position, accountId, positionContract, posSize, avgCost); + api.emit(EventName.positionEnd); }); }); diff --git a/src/tests/unit/api/order/placeOrder.test.ts b/src/tests/unit/api/order/placeOrder.test.ts index 1581f430..8f1caaa5 100644 --- a/src/tests/unit/api/order/placeOrder.test.ts +++ b/src/tests/unit/api/order/placeOrder.test.ts @@ -22,7 +22,7 @@ const awaitTimeout = (delay: number): Promise => new Promise((resolve): NodeJS.Timeout => setTimeout(resolve, delay * 1000)); describe("PlaceOrder", () => { - jest.setTimeout(10000); + jest.setTimeout(15000); let ib: IBApi; let clientId = Math.floor(Math.random() * 32766) + 1; // ensure unique client @@ -105,7 +105,7 @@ describe("PlaceOrder", () => { }); // Give a few secs delay to get order placed - awaitTimeout(5).then(() => ib.reqOpenOrders()); + awaitTimeout(10).then(() => ib.reqOpenOrders()); }); ib.connect(); @@ -187,7 +187,7 @@ describe("PlaceOrder", () => { }); // Give a few secs delay to get order placed - awaitTimeout(5).then(() => ib.reqOpenOrders()); + awaitTimeout(10).then(() => ib.reqOpenOrders()); }); ib.connect(); diff --git a/src/tools/account-summary.ts b/src/tools/account-summary.ts index a38ceee6..5fb2cca5 100644 --- a/src/tools/account-summary.ts +++ b/src/tools/account-summary.ts @@ -2,7 +2,6 @@ * This App will print IBKR account summaries to console. */ -import path from "path"; import { Subscription } from "rxjs"; import { IBApiNextError } from "../api-next"; @@ -58,9 +57,7 @@ class PrintAccountSummaryApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); this.subscription$ = this.api .getAccountSummary( diff --git a/src/tools/commission-reports.ts b/src/tools/commission-reports.ts index f22784ab..877f852c 100644 --- a/src/tools/commission-reports.ts +++ b/src/tools/commission-reports.ts @@ -1,7 +1,6 @@ /** * This App will print IBKR account place new orders to console. */ -import path from "path"; import { ExecutionFilter } from ".."; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -27,9 +26,7 @@ class CommissionReportApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); const executionFilter: ExecutionFilter = { clientId: "0", diff --git a/src/tools/common/ib-api-next-app.ts b/src/tools/common/ib-api-next-app.ts index 4e2ee9c7..beaa54d9 100644 --- a/src/tools/common/ib-api-next-app.ts +++ b/src/tools/common/ib-api-next-app.ts @@ -1,6 +1,7 @@ import { Subscription } from "rxjs"; -import { IBApiNext } from "../../api-next"; +import path from "path"; +import { IBApiNext, MarketDataType } from "../../api-next"; import Contract from "../../api/contract/contract"; import LogLevel from "../../api/data/enum/log-level"; import OptionType from "../../api/data/enum/option-type"; @@ -273,4 +274,12 @@ export class IBApiNextApp { right: this.cmdLineArgs.right as OptionType, }; } + + /** app startup */ + start(): void { + const scriptName = path.basename(__filename); + this.info(`Starting ${scriptName} script`); + this.connect(); + this.api.setMarketDataType(MarketDataType.DELAYED_FROZEN); + } } diff --git a/src/tools/contract-details.ts b/src/tools/contract-details.ts index 50586dcd..f1e78975 100644 --- a/src/tools/contract-details.ts +++ b/src/tools/contract-details.ts @@ -2,8 +2,6 @@ * This App will request contract details from TWS and print it to console. */ -import path from "path"; - import { IBApiNextError } from "../api-next"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -33,9 +31,7 @@ class PrintContractDetailsApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); this.api .getContractDetails(this.getContractArg()) diff --git a/src/tools/current-time.ts b/src/tools/current-time.ts index 9b374c08..4bd7ac44 100644 --- a/src/tools/current-time.ts +++ b/src/tools/current-time.ts @@ -2,8 +2,6 @@ * This App will print current TWS time to console. */ -import path from "path"; - import { IBApiNextError } from "../api-next"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -29,9 +27,7 @@ class PrintCurrentTimeApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); // print current time diff --git a/src/tools/execution-details.ts b/src/tools/execution-details.ts index c73fac2c..120a4243 100644 --- a/src/tools/execution-details.ts +++ b/src/tools/execution-details.ts @@ -1,7 +1,6 @@ /** * This App will print IBKR account place new orders to console. */ -import path from "path"; import { ExecutionFilter } from ".."; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -27,9 +26,7 @@ class CloseOrdersApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); const executionFilter: ExecutionFilter = { clientId: "0", diff --git a/src/tools/get-head-timestamp.ts b/src/tools/get-head-timestamp.ts index 31bd2f10..fe84cf6b 100644 --- a/src/tools/get-head-timestamp.ts +++ b/src/tools/get-head-timestamp.ts @@ -2,8 +2,6 @@ * This App will print the timestamp of earliest available historical data for a contract. */ -import path from "path"; - import { IBApiNextError } from "../api-next"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -33,9 +31,7 @@ class PrintHeadTimestampApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); // print next unused order id this.api diff --git a/src/tools/histogram-data.ts b/src/tools/histogram-data.ts index 46070dbe..eb0927c0 100644 --- a/src/tools/histogram-data.ts +++ b/src/tools/histogram-data.ts @@ -1,7 +1,6 @@ /** * This App will print histogram data of a contract. */ -import path from "path"; import { IBApiNextError } from "../api-next"; import DurationUnit from "../api/data/enum/duration-unit"; @@ -41,9 +40,7 @@ class PrintHistogramDataApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); if (!this.cmdLineArgs.conid) { this.error("-conid argument missing."); diff --git a/src/tools/historical-data-updates.ts b/src/tools/historical-data-updates.ts index b953303c..d25931c2 100644 --- a/src/tools/historical-data-updates.ts +++ b/src/tools/historical-data-updates.ts @@ -1,7 +1,6 @@ /** * This App will print real-time updates of the latest historical data bar of a contract. */ -import path from "path"; import { Subscription } from "rxjs"; import { IBApiNextError } from "../api-next"; @@ -41,9 +40,7 @@ class PrintPositionsApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); if (!this.cmdLineArgs.conid) { this.error("-conid argument missing."); diff --git a/src/tools/historical-data.ts b/src/tools/historical-data.ts index c71de36d..09cf7fed 100644 --- a/src/tools/historical-data.ts +++ b/src/tools/historical-data.ts @@ -1,7 +1,6 @@ /** * This App will print historical chart data of a contract. */ -import path from "path"; import { IBApiNextError } from "../api-next"; import { BarSizeSetting } from "../api/historical/bar-size-setting"; @@ -45,9 +44,7 @@ class PrintPositionsApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); if (!this.cmdLineArgs.conid) { this.error("-conid argument missing."); diff --git a/src/tools/historical-ticks-bid-ask.ts b/src/tools/historical-ticks-bid-ask.ts index 30937355..35fb6702 100644 --- a/src/tools/historical-ticks-bid-ask.ts +++ b/src/tools/historical-ticks-bid-ask.ts @@ -1,7 +1,6 @@ /** * This App will print historical bid / ask price Time&Sales data of and instrument. */ -import path from "path"; import { lastValueFrom } from "rxjs"; import { IBApiNextError } from "../api-next"; @@ -53,9 +52,7 @@ class PrintHistoricalTicksMidApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); if (!this.cmdLineArgs.conid) { this.error("-conid argument missing."); diff --git a/src/tools/historical-ticks-last.ts b/src/tools/historical-ticks-last.ts index de9f4df0..af20aa85 100644 --- a/src/tools/historical-ticks-last.ts +++ b/src/tools/historical-ticks-last.ts @@ -1,7 +1,6 @@ /** * This App will print historical last trade price Time&Sales data of and instrument. */ -import path from "path"; import { lastValueFrom, Subscription } from "rxjs"; import { IBApiNextError } from "../api-next"; @@ -56,9 +55,7 @@ class PrintHistoricalTicksLastApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); if (!this.cmdLineArgs.conid) { this.error("-conid argument missing."); diff --git a/src/tools/historical-ticks-mid.ts b/src/tools/historical-ticks-mid.ts index d9fe50e1..a0b563d1 100644 --- a/src/tools/historical-ticks-mid.ts +++ b/src/tools/historical-ticks-mid.ts @@ -1,7 +1,6 @@ /** * This App will print historical mid price Time&Sales data of and instrument. */ -import path from "path"; import { lastValueFrom } from "rxjs"; import { IBApiNextError } from "../api-next"; @@ -53,9 +52,7 @@ class PrintHistoricalTicksMidApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); if (!this.cmdLineArgs.conid) { this.error("-conid argument missing."); diff --git a/src/tools/managed-accts.ts b/src/tools/managed-accts.ts index 02cff8f1..8a62d536 100644 --- a/src/tools/managed-accts.ts +++ b/src/tools/managed-accts.ts @@ -2,8 +2,6 @@ * This App will print the accounts to which the logged user has access to. */ -import path from "path"; - import { IBApiNextError } from "../api-next"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -30,9 +28,7 @@ class PrintManagedAcctsApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); this.api .getManagedAccounts() diff --git a/src/tools/market-data-snapshot.ts b/src/tools/market-data-snapshot.ts index 180e648b..2556468a 100644 --- a/src/tools/market-data-snapshot.ts +++ b/src/tools/market-data-snapshot.ts @@ -2,15 +2,9 @@ * This App will print real time market data of a given contract id. */ -import path from "path"; import { Subscription } from "rxjs"; -import { - IBApiNextError, - IBApiNextTickType, - IBApiTickType, - MarketDataType, -} from "../api-next"; +import { IBApiNextError, IBApiNextTickType, IBApiTickType } from "../api-next"; import { IBApiNextApp } from "./common/ib-api-next-app"; ///////////////////////////////////////////////////////////////////////////////// @@ -43,10 +37,7 @@ class PrintMarketDataSingleApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); - this.api.setMarketDataType(MarketDataType.DELAYED_FROZEN); + super.start(); this.api .getMarketDataSnapshot( diff --git a/src/tools/market-data.ts b/src/tools/market-data.ts index bbbef269..82cc171f 100644 --- a/src/tools/market-data.ts +++ b/src/tools/market-data.ts @@ -2,15 +2,9 @@ * This App will print real time market data of a given contract id. */ -import path from "path"; import { Subscription } from "rxjs"; -import { - IBApiNextError, - IBApiNextTickType, - IBApiTickType, - MarketDataType, -} from "../api-next"; +import { IBApiNextError, IBApiNextTickType, IBApiTickType } from "../api-next"; import { IBApiNextApp } from "./common/ib-api-next-app"; ///////////////////////////////////////////////////////////////////////////////// @@ -42,10 +36,7 @@ class PrintMarketDataApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); - this.api.setMarketDataType(MarketDataType.DELAYED_FROZEN); + super.start(); this.subscription$ = this.api .getMarketData( diff --git a/src/tools/market-depth-exchanges.ts b/src/tools/market-depth-exchanges.ts index 34474908..f5133101 100644 --- a/src/tools/market-depth-exchanges.ts +++ b/src/tools/market-depth-exchanges.ts @@ -2,8 +2,6 @@ * This App will print the venues for which market data is returned on getMarketDepthL2 (those with market makers) */ -import path from "path"; - import { IBApiNextError } from "../api-next"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -30,9 +28,7 @@ class PrintMarketDepthExchangesApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); // print current time diff --git a/src/tools/market-depth.ts b/src/tools/market-depth.ts index 1fbe3047..aa36c7fc 100644 --- a/src/tools/market-depth.ts +++ b/src/tools/market-depth.ts @@ -2,7 +2,6 @@ * This App will print a contract's market depth (order book). */ -import path from "path"; import { Subscription } from "rxjs"; import { IBApiNextError } from "../api-next"; @@ -42,9 +41,7 @@ class PrintMarketDepthExchangesApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); if (!this.cmdLineArgs.conid) { this.error("-conid argument missing."); diff --git a/src/tools/market-scanner.ts b/src/tools/market-scanner.ts index 2bc7fa66..4a695c20 100644 --- a/src/tools/market-scanner.ts +++ b/src/tools/market-scanner.ts @@ -1,7 +1,6 @@ /** * This App will print Most active stocks. */ -import path from "path"; import { Subscription } from "rxjs"; import { IBApiNextError } from "../api-next"; @@ -38,9 +37,7 @@ class PrintMarketScreenerApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); this.subscription$ = this.api .getMarketScanner({ diff --git a/src/tools/modify-order.ts b/src/tools/modify-order.ts index 7747404c..dc2a3505 100644 --- a/src/tools/modify-order.ts +++ b/src/tools/modify-order.ts @@ -2,8 +2,6 @@ * This App will print IBKR account modify orders to console. */ -import path from "path"; - import { Contract, Order, OrderAction, OrderType, SecType } from "../"; import configuration from "../common/configuration"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -33,9 +31,7 @@ class ModifyOrdersApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); const id: number = +this.cmdLineArgs.orderId; diff --git a/src/tools/next-valid-order-id.ts b/src/tools/next-valid-order-id.ts index a42cdb6b..b4f90162 100644 --- a/src/tools/next-valid-order-id.ts +++ b/src/tools/next-valid-order-id.ts @@ -2,8 +2,6 @@ * This App will print the next valid unused order id. */ -import path from "path"; - import { IBApiNextError } from "../api-next"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -29,9 +27,7 @@ class PrintNextUnusedOrderIdApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); // print next unused order id diff --git a/src/tools/open-orders-auto.ts b/src/tools/open-orders-auto.ts index bbd13bc6..252d997f 100644 --- a/src/tools/open-orders-auto.ts +++ b/src/tools/open-orders-auto.ts @@ -2,7 +2,6 @@ * This App will print real-time updates of the IBKR account open orders. */ -import path from "path"; import { Subscription } from "rxjs"; import { IBApiNextError } from "../"; @@ -33,9 +32,7 @@ class OpenOrdersApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); this.subscription$ = this.api .getAutoOpenOrders(this.cmdLineArgs.bind ? true : false) diff --git a/src/tools/open-orders.ts b/src/tools/open-orders.ts index 4ee76654..80c2aa2a 100644 --- a/src/tools/open-orders.ts +++ b/src/tools/open-orders.ts @@ -2,8 +2,6 @@ * This App will print IBKR account open orders to console. */ -import path from "path"; - import { IBApiNextError } from "../"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -29,9 +27,7 @@ class OpenOrdersApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); this.api .getAllOpenOrders() diff --git a/src/tools/place-new-order.ts b/src/tools/place-new-order.ts index 086340c1..4d93776a 100644 --- a/src/tools/place-new-order.ts +++ b/src/tools/place-new-order.ts @@ -2,8 +2,6 @@ * This App will print IBKR account place new orders to console. */ -import path from "path"; - import { Contract, Order, OrderAction, OrderType, SecType } from "../"; import configuration from "../common/configuration"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -34,9 +32,7 @@ class PlaceNewOrdersApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); const contract: Contract = { symbol: this.cmdLineArgs.symbol as string, diff --git a/src/tools/place-order.ts b/src/tools/place-order.ts index 386e38f3..c54a33d0 100644 --- a/src/tools/place-order.ts +++ b/src/tools/place-order.ts @@ -43,8 +43,7 @@ class App extends IBApiNextApp { * Start the app. */ start(): void { - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); this.api .getNextValidOrderId() diff --git a/src/tools/pnl-single.ts b/src/tools/pnl-single.ts index 6464f712..2569759f 100644 --- a/src/tools/pnl-single.ts +++ b/src/tools/pnl-single.ts @@ -1,7 +1,6 @@ /** * This App will print real time updates for daily PnL of individual positions. */ -import path from "path"; import { Subscription } from "rxjs"; import { IBApiNextError } from "../api-next"; @@ -40,9 +39,7 @@ class PrintPositionsApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); if (!this.cmdLineArgs.account) { this.error("-account argument missing."); diff --git a/src/tools/pnl.ts b/src/tools/pnl.ts index 014687e0..70540d32 100644 --- a/src/tools/pnl.ts +++ b/src/tools/pnl.ts @@ -1,7 +1,6 @@ /** * This App will print daily PnL and unrealized PnL for a given account id. */ -import path from "path"; import { Subscription } from "rxjs"; import { IBApiNextError } from "../api-next"; @@ -35,9 +34,7 @@ class PrintPositionsApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); if (!this.cmdLineArgs.account) { this.error("-account argument missing."); diff --git a/src/tools/positions.ts b/src/tools/positions.ts index d4905de5..1cda2fdb 100644 --- a/src/tools/positions.ts +++ b/src/tools/positions.ts @@ -2,7 +2,6 @@ * This App will print all positions on your IBKR accounts to console. */ -import path from "path"; import { Subscription } from "rxjs"; import { IBApiNextError } from "../api-next"; @@ -34,9 +33,7 @@ class PrintPositionsApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); this.subscription$ = this.api.getPositions().subscribe({ next: (positions) => { diff --git a/src/tools/search-contracts.ts b/src/tools/search-contracts.ts index f1ab9075..7aa158ec 100644 --- a/src/tools/search-contracts.ts +++ b/src/tools/search-contracts.ts @@ -3,7 +3,6 @@ * to console. */ -import path from "path"; import { IBApiNextError } from "../api-next"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -31,9 +30,7 @@ class PrintContractSearchApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); if (!this.cmdLineArgs.pattern) { this.error("-pattern argument missing."); diff --git a/src/tools/sec-def-opt-params.ts b/src/tools/sec-def-opt-params.ts index 8b7131bd..fb49b702 100644 --- a/src/tools/sec-def-opt-params.ts +++ b/src/tools/sec-def-opt-params.ts @@ -2,8 +2,6 @@ * This App will request security definition option parameters from TWS and print it to console. */ -import path from "path"; - import { SecType } from "../"; import { IBApiNextError } from "../api-next"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -40,9 +38,7 @@ class PrintOptionsDetailsApp extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); this.api .getSecDefOptParams( diff --git a/src/tools/user-info.ts b/src/tools/user-info.ts index 1e744bb0..fdee690a 100644 --- a/src/tools/user-info.ts +++ b/src/tools/user-info.ts @@ -2,8 +2,6 @@ * This App will print the user info of the logged user. */ -import path from "path"; - import { IBApiNextError } from "../api-next"; import { IBApiNextApp } from "./common/ib-api-next-app"; @@ -29,9 +27,7 @@ class App extends IBApiNextApp { * Start the app. */ start(): void { - const scriptName = path.basename(__filename); - this.info(`Starting ${scriptName} script`); - this.connect(); + super.start(); this.api .getUserInfo() diff --git a/yarn.lock b/yarn.lock index 18507503..176c68a6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -455,27 +455,27 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/console@^29.6.4": - version "29.6.4" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.6.4.tgz#a7e2d84516301f986bba0dd55af9d5fe37f46527" - integrity sha512-wNK6gC0Ha9QeEPSkeJedQuTQqxZYnDPuDcDhVuVatRvMkL4D0VTvFVZj+Yuh6caG2aOfzkUZ36KtCmLNtR02hw== +"@jest/console@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-29.7.0.tgz#cd4822dbdb84529265c5a2bdb529a3c9cc950ffc" + integrity sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg== dependencies: "@jest/types" "^29.6.3" "@types/node" "*" chalk "^4.0.0" - jest-message-util "^29.6.3" - jest-util "^29.6.3" + jest-message-util "^29.7.0" + jest-util "^29.7.0" slash "^3.0.0" -"@jest/core@^29.6.4": - version "29.6.4" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.6.4.tgz#265ebee05ec1ff3567757e7a327155c8d6bdb126" - integrity sha512-U/vq5ccNTSVgYH7mHnodHmCffGWHJnz/E1BEWlLuK5pM4FZmGfBn/nrJGLjUsSmyx3otCeqc1T31F4y08AMDLg== +"@jest/core@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-29.7.0.tgz#b6cccc239f30ff36609658c5a5e2291757ce448f" + integrity sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg== dependencies: - "@jest/console" "^29.6.4" - "@jest/reporters" "^29.6.4" - "@jest/test-result" "^29.6.4" - "@jest/transform" "^29.6.4" + "@jest/console" "^29.7.0" + "@jest/reporters" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" "@jest/types" "^29.6.3" "@types/node" "*" ansi-escapes "^4.2.1" @@ -483,33 +483,33 @@ ci-info "^3.2.0" exit "^0.1.2" graceful-fs "^4.2.9" - jest-changed-files "^29.6.3" - jest-config "^29.6.4" - jest-haste-map "^29.6.4" - jest-message-util "^29.6.3" + jest-changed-files "^29.7.0" + jest-config "^29.7.0" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" jest-regex-util "^29.6.3" - jest-resolve "^29.6.4" - jest-resolve-dependencies "^29.6.4" - jest-runner "^29.6.4" - jest-runtime "^29.6.4" - jest-snapshot "^29.6.4" - jest-util "^29.6.3" - jest-validate "^29.6.3" - jest-watcher "^29.6.4" + jest-resolve "^29.7.0" + jest-resolve-dependencies "^29.7.0" + jest-runner "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" + jest-watcher "^29.7.0" micromatch "^4.0.4" - pretty-format "^29.6.3" + pretty-format "^29.7.0" slash "^3.0.0" strip-ansi "^6.0.0" -"@jest/environment@^29.6.4": - version "29.6.4" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.6.4.tgz#78ec2c9f8c8829a37616934ff4fea0c028c79f4f" - integrity sha512-sQ0SULEjA1XUTHmkBRl7A1dyITM9yb1yb3ZNKPX3KlTd6IG7mWUe3e2yfExtC2Zz1Q+mMckOLHmL/qLiuQJrBQ== +"@jest/environment@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-29.7.0.tgz#24d61f54ff1f786f3cd4073b4b94416383baf2a7" + integrity sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw== dependencies: - "@jest/fake-timers" "^29.6.4" + "@jest/fake-timers" "^29.7.0" "@jest/types" "^29.6.3" "@types/node" "*" - jest-mock "^29.6.3" + jest-mock "^29.7.0" "@jest/expect-utils@^29.6.4": version "29.6.4" @@ -518,45 +518,52 @@ dependencies: jest-get-type "^29.6.3" -"@jest/expect@^29.6.4": - version "29.6.4" - resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.6.4.tgz#1d6ae17dc68d906776198389427ab7ce6179dba6" - integrity sha512-Warhsa7d23+3X5bLbrbYvaehcgX5TLYhI03JKoedTiI8uJU4IhqYBWF7OSSgUyz4IgLpUYPkK0AehA5/fRclAA== +"@jest/expect-utils@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" + integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== dependencies: - expect "^29.6.4" - jest-snapshot "^29.6.4" + jest-get-type "^29.6.3" -"@jest/fake-timers@^29.6.4": - version "29.6.4" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.6.4.tgz#45a27f093c43d5d989362a3e7a8c70c83188b4f6" - integrity sha512-6UkCwzoBK60edXIIWb0/KWkuj7R7Qq91vVInOe3De6DSpaEiqjKcJw4F7XUet24Wupahj9J6PlR09JqJ5ySDHw== +"@jest/expect@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-29.7.0.tgz#76a3edb0cb753b70dfbfe23283510d3d45432bf2" + integrity sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ== + dependencies: + expect "^29.7.0" + jest-snapshot "^29.7.0" + +"@jest/fake-timers@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-29.7.0.tgz#fd91bf1fffb16d7d0d24a426ab1a47a49881a565" + integrity sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ== dependencies: "@jest/types" "^29.6.3" "@sinonjs/fake-timers" "^10.0.2" "@types/node" "*" - jest-message-util "^29.6.3" - jest-mock "^29.6.3" - jest-util "^29.6.3" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" + jest-util "^29.7.0" -"@jest/globals@^29.6.4": - version "29.6.4" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.6.4.tgz#4f04f58731b062b44ef23036b79bdb31f40c7f63" - integrity sha512-wVIn5bdtjlChhXAzVXavcY/3PEjf4VqM174BM3eGL5kMxLiZD5CLnbmkEyA1Dwh9q8XjP6E8RwjBsY/iCWrWsA== +"@jest/globals@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-29.7.0.tgz#8d9290f9ec47ff772607fa864ca1d5a2efae1d4d" + integrity sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ== dependencies: - "@jest/environment" "^29.6.4" - "@jest/expect" "^29.6.4" + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" "@jest/types" "^29.6.3" - jest-mock "^29.6.3" + jest-mock "^29.7.0" -"@jest/reporters@^29.6.4": - version "29.6.4" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.6.4.tgz#9d6350c8a2761ece91f7946e97ab0dabc06deab7" - integrity sha512-sxUjWxm7QdchdrD3NfWKrL8FBsortZeibSJv4XLjESOOjSUOkjQcb0ZHJwfhEGIvBvTluTzfG2yZWZhkrXJu8g== +"@jest/reporters@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-29.7.0.tgz#04b262ecb3b8faa83b0b3d321623972393e8f4c7" + integrity sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg== dependencies: "@bcoe/v8-coverage" "^0.2.3" - "@jest/console" "^29.6.4" - "@jest/test-result" "^29.6.4" - "@jest/transform" "^29.6.4" + "@jest/console" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" "@jest/types" "^29.6.3" "@jridgewell/trace-mapping" "^0.3.18" "@types/node" "*" @@ -570,9 +577,9 @@ istanbul-lib-report "^3.0.0" istanbul-lib-source-maps "^4.0.0" istanbul-reports "^3.1.3" - jest-message-util "^29.6.3" - jest-util "^29.6.3" - jest-worker "^29.6.4" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + jest-worker "^29.7.0" slash "^3.0.0" string-length "^4.0.1" strip-ansi "^6.0.0" @@ -594,30 +601,30 @@ callsites "^3.0.0" graceful-fs "^4.2.9" -"@jest/test-result@^29.6.4": - version "29.6.4" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.6.4.tgz#adf5c79f6e1fb7405ad13d67d9e2b6ff54b54c6b" - integrity sha512-uQ1C0AUEN90/dsyEirgMLlouROgSY+Wc/JanVVk0OiUKa5UFh7sJpMEM3aoUBAz2BRNvUJ8j3d294WFuRxSyOQ== +"@jest/test-result@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-29.7.0.tgz#8db9a80aa1a097bb2262572686734baed9b1657c" + integrity sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA== dependencies: - "@jest/console" "^29.6.4" + "@jest/console" "^29.7.0" "@jest/types" "^29.6.3" "@types/istanbul-lib-coverage" "^2.0.0" collect-v8-coverage "^1.0.0" -"@jest/test-sequencer@^29.6.4": - version "29.6.4" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.6.4.tgz#86aef66aaa22b181307ed06c26c82802fb836d7b" - integrity sha512-E84M6LbpcRq3fT4ckfKs9ryVanwkaIB0Ws9bw3/yP4seRLg/VaCZ/LgW0MCq5wwk4/iP/qnilD41aj2fsw2RMg== +"@jest/test-sequencer@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz#6cef977ce1d39834a3aea887a1726628a6f072ce" + integrity sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw== dependencies: - "@jest/test-result" "^29.6.4" + "@jest/test-result" "^29.7.0" graceful-fs "^4.2.9" - jest-haste-map "^29.6.4" + jest-haste-map "^29.7.0" slash "^3.0.0" -"@jest/transform@^29.6.4": - version "29.6.4" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.6.4.tgz#a6bc799ef597c5d85b2e65a11fd96b6b239bab5a" - integrity sha512-8thgRSiXUqtr/pPGY/OsyHuMjGyhVnWrFAwoxmIemlBuiMyU1WFs0tXoNxzcr4A4uErs/ABre76SGmrr5ab/AA== +"@jest/transform@^29.7.0": + version "29.7.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-29.7.0.tgz#df2dd9c346c7d7768b8a06639994640c642e284c" + integrity sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw== dependencies: "@babel/core" "^7.11.6" "@jest/types" "^29.6.3" @@ -627,9 +634,9 @@ convert-source-map "^2.0.0" fast-json-stable-stringify "^2.1.0" graceful-fs "^4.2.9" - jest-haste-map "^29.6.4" + jest-haste-map "^29.7.0" jest-regex-util "^29.6.3" - jest-util "^29.6.3" + jest-util "^29.7.0" micromatch "^4.0.4" pirates "^4.0.4" slash "^3.0.0" @@ -835,16 +842,16 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.6.0.tgz#19ba09aa34fd504696445100262e5a9e1b1d7024" - integrity sha512-CW9YDGTQnNYMIo5lMeuiIG08p4E0cXrXTbcZ2saT/ETE7dWUrNxlijsQeU04qAAKkILiLzdQz+cGFxCJjaZUmA== +"@typescript-eslint/eslint-plugin@^6.7.0": + version "6.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.7.0.tgz#ed2a38867190f8a688af85ad7c8a74670b8b3675" + integrity sha512-gUqtknHm0TDs1LhY12K2NA3Rmlmp88jK9Tx8vGZMfHeNMLE3GH2e9TRub+y+SOjuYgtOmok+wt1AyDPZqxbNag== dependencies: "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "6.6.0" - "@typescript-eslint/type-utils" "6.6.0" - "@typescript-eslint/utils" "6.6.0" - "@typescript-eslint/visitor-keys" "6.6.0" + "@typescript-eslint/scope-manager" "6.7.0" + "@typescript-eslint/type-utils" "6.7.0" + "@typescript-eslint/utils" "6.7.0" + "@typescript-eslint/visitor-keys" "6.7.0" debug "^4.3.4" graphemer "^1.4.0" ignore "^5.2.4" @@ -859,15 +866,15 @@ dependencies: "@typescript-eslint/utils" "5.62.0" -"@typescript-eslint/parser@^6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.6.0.tgz#fe323a7b4eafb6d5ea82b96216561810394a739e" - integrity sha512-setq5aJgUwtzGrhW177/i+DMLqBaJbdwGj2CPIVFFLE0NCliy5ujIdLHd2D1ysmlmsjdL2GWW+hR85neEfc12w== +"@typescript-eslint/parser@^6.7.0": + version "6.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.7.0.tgz#332fe9c7ecf6783d3250b4c8a960bd4af0995807" + integrity sha512-jZKYwqNpNm5kzPVP5z1JXAuxjtl2uG+5NpaMocFPTNC2EdYIgbXIPImObOkhbONxtFTTdoZstLZefbaK+wXZng== dependencies: - "@typescript-eslint/scope-manager" "6.6.0" - "@typescript-eslint/types" "6.6.0" - "@typescript-eslint/typescript-estree" "6.6.0" - "@typescript-eslint/visitor-keys" "6.6.0" + "@typescript-eslint/scope-manager" "6.7.0" + "@typescript-eslint/types" "6.7.0" + "@typescript-eslint/typescript-estree" "6.7.0" + "@typescript-eslint/visitor-keys" "6.7.0" debug "^4.3.4" "@typescript-eslint/scope-manager@5.62.0": @@ -878,21 +885,21 @@ "@typescript-eslint/types" "5.62.0" "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/scope-manager@6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.6.0.tgz#57105d4419d6de971f7d2c30a2ff4ac40003f61a" - integrity sha512-pT08u5W/GT4KjPUmEtc2kSYvrH8x89cVzkA0Sy2aaOUIw6YxOIjA8ilwLr/1fLjOedX1QAuBpG9XggWqIIfERw== +"@typescript-eslint/scope-manager@6.7.0": + version "6.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.7.0.tgz#6b3c22187976e2bf5ed0dc0d9095f1f2cbd1d106" + integrity sha512-lAT1Uau20lQyjoLUQ5FUMSX/dS07qux9rYd5FGzKz/Kf8W8ccuvMyldb8hadHdK/qOI7aikvQWqulnEq2nCEYA== dependencies: - "@typescript-eslint/types" "6.6.0" - "@typescript-eslint/visitor-keys" "6.6.0" + "@typescript-eslint/types" "6.7.0" + "@typescript-eslint/visitor-keys" "6.7.0" -"@typescript-eslint/type-utils@6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.6.0.tgz#14f651d13b884915c4fca0d27adeb652a4499e86" - integrity sha512-8m16fwAcEnQc69IpeDyokNO+D5spo0w1jepWWY2Q6y5ZKNuj5EhVQXjtVAeDDqvW6Yg7dhclbsz6rTtOvcwpHg== +"@typescript-eslint/type-utils@6.7.0": + version "6.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.7.0.tgz#21a013d4c7f96255f5e64ac59fb41301d1e052ba" + integrity sha512-f/QabJgDAlpSz3qduCyQT0Fw7hHpmhOzY/Rv6zO3yO+HVIdPfIWhrQoAyG+uZVtWAIS85zAyzgAFfyEr+MgBpg== dependencies: - "@typescript-eslint/typescript-estree" "6.6.0" - "@typescript-eslint/utils" "6.6.0" + "@typescript-eslint/typescript-estree" "6.7.0" + "@typescript-eslint/utils" "6.7.0" debug "^4.3.4" ts-api-utils "^1.0.1" @@ -901,10 +908,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/types@6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.6.0.tgz#95e7ea650a2b28bc5af5ea8907114a48f54618c2" - integrity sha512-CB6QpJQ6BAHlJXdwUmiaXDBmTqIE2bzGTDLADgvqtHWuhfNP3rAOK7kAgRMAET5rDRr9Utt+qAzRBdu3AhR3sg== +"@typescript-eslint/types@6.7.0": + version "6.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.7.0.tgz#8de8ba9cafadc38e89003fe303e219c9250089ae" + integrity sha512-ihPfvOp7pOcN/ysoj0RpBPOx3HQTJTrIN8UZK+WFd3/iDeFHHqeyYxa4hQk4rMhsz9H9mXpR61IzwlBVGXtl9Q== "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" @@ -919,13 +926,13 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.6.0.tgz#373c420d2e12c28220f4a83352280a04823a91b7" - integrity sha512-hMcTQ6Al8MP2E6JKBAaSxSVw5bDhdmbCEhGW/V8QXkb9oNsFkA4SBuOMYVPxD3jbtQ4R/vSODBsr76R6fP3tbA== +"@typescript-eslint/typescript-estree@6.7.0": + version "6.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.7.0.tgz#20ce2801733bd46f02cc0f141f5b63fbbf2afb63" + integrity sha512-dPvkXj3n6e9yd/0LfojNU8VMUGHWiLuBZvbM6V6QYD+2qxqInE7J+J/ieY2iGwR9ivf/R/haWGkIj04WVUeiSQ== dependencies: - "@typescript-eslint/types" "6.6.0" - "@typescript-eslint/visitor-keys" "6.6.0" + "@typescript-eslint/types" "6.7.0" + "@typescript-eslint/visitor-keys" "6.7.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -946,17 +953,17 @@ eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/utils@6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.6.0.tgz#2d686c0f0786da6362d909e27a9de1c13ba2e7dc" - integrity sha512-mPHFoNa2bPIWWglWYdR0QfY9GN0CfvvXX1Sv6DlSTive3jlMTUy+an67//Gysc+0Me9pjitrq0LJp0nGtLgftw== +"@typescript-eslint/utils@6.7.0": + version "6.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.7.0.tgz#61b6f1f1b82ad529abfcee074d21764e880886fb" + integrity sha512-MfCq3cM0vh2slSikQYqK2Gq52gvOhe57vD2RM3V4gQRZYX4rDPnKLu5p6cm89+LJiGlwEXU8hkYxhqqEC/V3qA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" "@types/json-schema" "^7.0.12" "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "6.6.0" - "@typescript-eslint/types" "6.6.0" - "@typescript-eslint/typescript-estree" "6.6.0" + "@typescript-eslint/scope-manager" "6.7.0" + "@typescript-eslint/types" "6.7.0" + "@typescript-eslint/typescript-estree" "6.7.0" semver "^7.5.4" "@typescript-eslint/visitor-keys@5.62.0": @@ -967,12 +974,12 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@typescript-eslint/visitor-keys@6.6.0": - version "6.6.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.6.0.tgz#1109088b4346c8b2446f3845db526374d9a3bafc" - integrity sha512-L61uJT26cMOfFQ+lMZKoJNbAEckLe539VhTxiGHrWl5XSKQgA0RTBZJW2HFPy5T0ZvPVSD93QsrTKDkfNwJGyQ== +"@typescript-eslint/visitor-keys@6.7.0": + version "6.7.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.7.0.tgz#34140ac76dfb6316d17012e4469acf3366ad3f44" + integrity sha512-/C1RVgKFDmGMcVGeD8HjKv2bd72oI1KxQDeY8uc66gw9R0OK0eMq48cA+jv9/2Ag6cdrsUGySm1yzYmfz0hxwQ== dependencies: - "@typescript-eslint/types" "6.6.0" + "@typescript-eslint/types" "6.7.0" eslint-visitor-keys "^3.4.1" acorn-jsx@^5.3.2: @@ -1066,12 +1073,12 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -babel-jest@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.6.4.tgz#98dbc45d1c93319c82a8ab4a478b670655dd2585" - integrity sha512-meLj23UlSLddj6PC+YTOFRgDAtjnZom8w/ACsrx0gtPtv5cJZk0A5Unk5bV4wixD7XaPCN1fQvpww8czkZURmw== +babel-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" + integrity sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg== dependencies: - "@jest/transform" "^29.6.4" + "@jest/transform" "^29.7.0" "@types/babel__core" "^7.1.14" babel-plugin-istanbul "^6.1.1" babel-preset-jest "^29.6.3" @@ -1328,6 +1335,19 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +create-jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320" + integrity sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q== + dependencies: + "@jest/types" "^29.6.3" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.9" + jest-config "^29.7.0" + jest-util "^29.7.0" + prompts "^2.0.1" + cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -1605,7 +1625,7 @@ exit@^0.1.2: resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ== -expect@^29.0.0, expect@^29.6.4: +expect@^29.0.0: version "29.6.4" resolved "https://registry.yarnpkg.com/expect/-/expect-29.6.4.tgz#a6e6f66d4613717859b2fe3da98a739437b6f4b8" integrity sha512-F2W2UyQ8XYyftHT57dtfg8Ue3X5qLgm2sSug0ivvLRH/VKNRL/pDxg/TH7zVzbQB0tu80clNFy6LU7OS/VSEKA== @@ -1616,6 +1636,17 @@ expect@^29.0.0, expect@^29.6.4: jest-message-util "^29.6.3" jest-util "^29.6.3" +expect@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" + integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== + dependencies: + "@jest/expect-utils" "^29.7.0" + jest-get-type "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -1990,84 +2021,83 @@ istanbul-reports@^3.1.3: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -jest-changed-files@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.6.3.tgz#97cfdc93f74fb8af2a1acb0b78f836f1fb40c449" - integrity sha512-G5wDnElqLa4/c66ma5PG9eRjE342lIbF6SUnTJi26C3J28Fv2TVY2rOyKB9YGbSA5ogwevgmxc4j4aVjrEK6Yg== +jest-changed-files@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-29.7.0.tgz#1c06d07e77c78e1585d020424dedc10d6e17ac3a" + integrity sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w== dependencies: execa "^5.0.0" - jest-util "^29.6.3" + jest-util "^29.7.0" p-limit "^3.1.0" -jest-circus@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.6.4.tgz#f074c8d795e0cc0f2ebf0705086b1be6a9a8722f" - integrity sha512-YXNrRyntVUgDfZbjXWBMPslX1mQ8MrSG0oM/Y06j9EYubODIyHWP8hMUbjbZ19M3M+zamqEur7O80HODwACoJw== +jest-circus@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-29.7.0.tgz#b6817a45fcc835d8b16d5962d0c026473ee3668a" + integrity sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw== dependencies: - "@jest/environment" "^29.6.4" - "@jest/expect" "^29.6.4" - "@jest/test-result" "^29.6.4" + "@jest/environment" "^29.7.0" + "@jest/expect" "^29.7.0" + "@jest/test-result" "^29.7.0" "@jest/types" "^29.6.3" "@types/node" "*" chalk "^4.0.0" co "^4.6.0" dedent "^1.0.0" is-generator-fn "^2.0.0" - jest-each "^29.6.3" - jest-matcher-utils "^29.6.4" - jest-message-util "^29.6.3" - jest-runtime "^29.6.4" - jest-snapshot "^29.6.4" - jest-util "^29.6.3" + jest-each "^29.7.0" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-runtime "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" p-limit "^3.1.0" - pretty-format "^29.6.3" + pretty-format "^29.7.0" pure-rand "^6.0.0" slash "^3.0.0" stack-utils "^2.0.3" -jest-cli@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.6.4.tgz#ad52f2dfa1b0291de7ec7f8d7c81ac435521ede0" - integrity sha512-+uMCQ7oizMmh8ZwRfZzKIEszFY9ksjjEQnTEMTaL7fYiL3Kw4XhqT9bYh+A4DQKUb67hZn2KbtEnDuHvcgK4pQ== +jest-cli@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-29.7.0.tgz#5592c940798e0cae677eec169264f2d839a37995" + integrity sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg== dependencies: - "@jest/core" "^29.6.4" - "@jest/test-result" "^29.6.4" + "@jest/core" "^29.7.0" + "@jest/test-result" "^29.7.0" "@jest/types" "^29.6.3" chalk "^4.0.0" + create-jest "^29.7.0" exit "^0.1.2" - graceful-fs "^4.2.9" import-local "^3.0.2" - jest-config "^29.6.4" - jest-util "^29.6.3" - jest-validate "^29.6.3" - prompts "^2.0.1" + jest-config "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" yargs "^17.3.1" -jest-config@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.6.4.tgz#eff958ee41d4e1ee7a6106d02b74ad9fc427d79e" - integrity sha512-JWohr3i9m2cVpBumQFv2akMEnFEPVOh+9L2xIBJhJ0zOaci2ZXuKJj0tgMKQCBZAKA09H049IR4HVS/43Qb19A== +jest-config@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-29.7.0.tgz#bcbda8806dbcc01b1e316a46bb74085a84b0245f" + integrity sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ== dependencies: "@babel/core" "^7.11.6" - "@jest/test-sequencer" "^29.6.4" + "@jest/test-sequencer" "^29.7.0" "@jest/types" "^29.6.3" - babel-jest "^29.6.4" + babel-jest "^29.7.0" chalk "^4.0.0" ci-info "^3.2.0" deepmerge "^4.2.2" glob "^7.1.3" graceful-fs "^4.2.9" - jest-circus "^29.6.4" - jest-environment-node "^29.6.4" + jest-circus "^29.7.0" + jest-environment-node "^29.7.0" jest-get-type "^29.6.3" jest-regex-util "^29.6.3" - jest-resolve "^29.6.4" - jest-runner "^29.6.4" - jest-util "^29.6.3" - jest-validate "^29.6.3" + jest-resolve "^29.7.0" + jest-runner "^29.7.0" + jest-util "^29.7.0" + jest-validate "^29.7.0" micromatch "^4.0.4" parse-json "^5.2.0" - pretty-format "^29.6.3" + pretty-format "^29.7.0" slash "^3.0.0" strip-json-comments "^3.1.1" @@ -2081,45 +2111,55 @@ jest-diff@^29.6.4: jest-get-type "^29.6.3" pretty-format "^29.6.3" -jest-docblock@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.6.3.tgz#293dca5188846c9f7c0c2b1bb33e5b11f21645f2" - integrity sha512-2+H+GOTQBEm2+qFSQ7Ma+BvyV+waiIFxmZF5LdpBsAEjWX8QYjSCa4FrkIYtbfXUJJJnFCYrOtt6TZ+IAiTjBQ== +jest-diff@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" + integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== + dependencies: + chalk "^4.0.0" + diff-sequences "^29.6.3" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + +jest-docblock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-29.7.0.tgz#8fddb6adc3cdc955c93e2a87f61cfd350d5d119a" + integrity sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g== dependencies: detect-newline "^3.0.0" -jest-each@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.6.3.tgz#1956f14f5f0cb8ae0b2e7cabc10bb03ec817c142" - integrity sha512-KoXfJ42k8cqbkfshW7sSHcdfnv5agDdHCPA87ZBdmHP+zJstTJc0ttQaJ/x7zK6noAL76hOuTIJ6ZkQRS5dcyg== +jest-each@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-29.7.0.tgz#162a9b3f2328bdd991beaabffbb74745e56577d1" + integrity sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ== dependencies: "@jest/types" "^29.6.3" chalk "^4.0.0" jest-get-type "^29.6.3" - jest-util "^29.6.3" - pretty-format "^29.6.3" + jest-util "^29.7.0" + pretty-format "^29.7.0" -jest-environment-node@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.6.4.tgz#4ce311549afd815d3cafb49e60a1e4b25f06d29f" - integrity sha512-i7SbpH2dEIFGNmxGCpSc2w9cA4qVD+wfvg2ZnfQ7XVrKL0NA5uDVBIiGH8SR4F0dKEv/0qI5r+aDomDf04DpEQ== +jest-environment-node@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-29.7.0.tgz#0b93e111dda8ec120bc8300e6d1fb9576e164376" + integrity sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw== dependencies: - "@jest/environment" "^29.6.4" - "@jest/fake-timers" "^29.6.4" + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" "@jest/types" "^29.6.3" "@types/node" "*" - jest-mock "^29.6.3" - jest-util "^29.6.3" + jest-mock "^29.7.0" + jest-util "^29.7.0" jest-get-type@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== -jest-haste-map@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.6.4.tgz#97143ce833829157ea7025204b08f9ace609b96a" - integrity sha512-12Ad+VNTDHxKf7k+M65sviyynRoZYuL1/GTuhEVb8RYsNSNln71nANRb/faSyWvx0j+gHcivChXHIoMJrGYjog== +jest-haste-map@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-29.7.0.tgz#3c2396524482f5a0506376e6c858c3bbcc17b104" + integrity sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA== dependencies: "@jest/types" "^29.6.3" "@types/graceful-fs" "^4.1.3" @@ -2128,8 +2168,8 @@ jest-haste-map@^29.6.4: fb-watchman "^2.0.0" graceful-fs "^4.2.9" jest-regex-util "^29.6.3" - jest-util "^29.6.3" - jest-worker "^29.6.4" + jest-util "^29.7.0" + jest-worker "^29.7.0" micromatch "^4.0.4" walker "^1.0.8" optionalDependencies: @@ -2145,13 +2185,13 @@ jest-junit@^16.0.0: uuid "^8.3.2" xml "^1.0.1" -jest-leak-detector@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.6.3.tgz#b9661bc3aec8874e59aff361fa0c6d7cd507ea01" - integrity sha512-0kfbESIHXYdhAdpLsW7xdwmYhLf1BRu4AA118/OxFm0Ho1b2RcTmO4oF6aAMaxpxdxnJ3zve2rgwzNBD4Zbm7Q== +jest-leak-detector@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz#5b7ec0dadfdfec0ca383dc9aa016d36b5ea4c728" + integrity sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw== dependencies: jest-get-type "^29.6.3" - pretty-format "^29.6.3" + pretty-format "^29.7.0" jest-matcher-utils@^29.6.4: version "29.6.4" @@ -2163,6 +2203,16 @@ jest-matcher-utils@^29.6.4: jest-get-type "^29.6.3" pretty-format "^29.6.3" +jest-matcher-utils@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" + integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== + dependencies: + chalk "^4.0.0" + jest-diff "^29.7.0" + jest-get-type "^29.6.3" + pretty-format "^29.7.0" + jest-message-util@^29.6.3: version "29.6.3" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.6.3.tgz#bce16050d86801b165f20cfde34dc01d3cf85fbf" @@ -2178,14 +2228,29 @@ jest-message-util@^29.6.3: slash "^3.0.0" stack-utils "^2.0.3" -jest-mock@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.6.3.tgz#433f3fd528c8ec5a76860177484940628bdf5e0a" - integrity sha512-Z7Gs/mOyTSR4yPsaZ72a/MtuK6RnC3JYqWONe48oLaoEcYwEDxqvbXz85G4SJrm2Z5Ar9zp6MiHF4AlFlRM4Pg== +jest-message-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" + integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== + dependencies: + "@babel/code-frame" "^7.12.13" + "@jest/types" "^29.6.3" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.9" + micromatch "^4.0.4" + pretty-format "^29.7.0" + slash "^3.0.0" + stack-utils "^2.0.3" + +jest-mock@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-29.7.0.tgz#4e836cf60e99c6fcfabe9f99d017f3fdd50a6347" + integrity sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw== dependencies: "@jest/types" "^29.6.3" "@types/node" "*" - jest-util "^29.6.3" + jest-util "^29.7.0" jest-pnp-resolver@^1.2.2: version "1.2.3" @@ -2197,67 +2262,67 @@ jest-regex-util@^29.6.3: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-29.6.3.tgz#4a556d9c776af68e1c5f48194f4d0327d24e8a52" integrity sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg== -jest-resolve-dependencies@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.4.tgz#20156b33c7eacbb6bb77aeba4bed0eab4a3f8734" - integrity sha512-7+6eAmr1ZBF3vOAJVsfLj1QdqeXG+WYhidfLHBRZqGN24MFRIiKG20ItpLw2qRAsW/D2ZUUmCNf6irUr/v6KHA== +jest-resolve-dependencies@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz#1b04f2c095f37fc776ff40803dc92921b1e88428" + integrity sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA== dependencies: jest-regex-util "^29.6.3" - jest-snapshot "^29.6.4" + jest-snapshot "^29.7.0" -jest-resolve@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.6.4.tgz#e34cb06f2178b429c38455d98d1a07572ac9faa3" - integrity sha512-fPRq+0vcxsuGlG0O3gyoqGTAxasagOxEuyoxHeyxaZbc9QNek0AmJWSkhjlMG+mTsj+8knc/mWb3fXlRNVih7Q== +jest-resolve@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-29.7.0.tgz#64d6a8992dd26f635ab0c01e5eef4399c6bcbc30" + integrity sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA== dependencies: chalk "^4.0.0" graceful-fs "^4.2.9" - jest-haste-map "^29.6.4" + jest-haste-map "^29.7.0" jest-pnp-resolver "^1.2.2" - jest-util "^29.6.3" - jest-validate "^29.6.3" + jest-util "^29.7.0" + jest-validate "^29.7.0" resolve "^1.20.0" resolve.exports "^2.0.0" slash "^3.0.0" -jest-runner@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.6.4.tgz#b3b8ccb85970fde0fae40c73ee11eb75adccfacf" - integrity sha512-SDaLrMmtVlQYDuG0iSPYLycG8P9jLI+fRm8AF/xPKhYDB2g6xDWjXBrR5M8gEWsK6KVFlebpZ4QsrxdyIX1Jaw== +jest-runner@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-29.7.0.tgz#809af072d408a53dcfd2e849a4c976d3132f718e" + integrity sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ== dependencies: - "@jest/console" "^29.6.4" - "@jest/environment" "^29.6.4" - "@jest/test-result" "^29.6.4" - "@jest/transform" "^29.6.4" + "@jest/console" "^29.7.0" + "@jest/environment" "^29.7.0" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" "@jest/types" "^29.6.3" "@types/node" "*" chalk "^4.0.0" emittery "^0.13.1" graceful-fs "^4.2.9" - jest-docblock "^29.6.3" - jest-environment-node "^29.6.4" - jest-haste-map "^29.6.4" - jest-leak-detector "^29.6.3" - jest-message-util "^29.6.3" - jest-resolve "^29.6.4" - jest-runtime "^29.6.4" - jest-util "^29.6.3" - jest-watcher "^29.6.4" - jest-worker "^29.6.4" + jest-docblock "^29.7.0" + jest-environment-node "^29.7.0" + jest-haste-map "^29.7.0" + jest-leak-detector "^29.7.0" + jest-message-util "^29.7.0" + jest-resolve "^29.7.0" + jest-runtime "^29.7.0" + jest-util "^29.7.0" + jest-watcher "^29.7.0" + jest-worker "^29.7.0" p-limit "^3.1.0" source-map-support "0.5.13" -jest-runtime@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.6.4.tgz#b0bc495c9b6b12a0a7042ac34ca9bb85f8cd0ded" - integrity sha512-s/QxMBLvmwLdchKEjcLfwzP7h+jsHvNEtxGP5P+Fl1FMaJX2jMiIqe4rJw4tFprzCwuSvVUo9bn0uj4gNRXsbA== +jest-runtime@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-29.7.0.tgz#efecb3141cf7d3767a3a0cc8f7c9990587d3d817" + integrity sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ== dependencies: - "@jest/environment" "^29.6.4" - "@jest/fake-timers" "^29.6.4" - "@jest/globals" "^29.6.4" + "@jest/environment" "^29.7.0" + "@jest/fake-timers" "^29.7.0" + "@jest/globals" "^29.7.0" "@jest/source-map" "^29.6.3" - "@jest/test-result" "^29.6.4" - "@jest/transform" "^29.6.4" + "@jest/test-result" "^29.7.0" + "@jest/transform" "^29.7.0" "@jest/types" "^29.6.3" "@types/node" "*" chalk "^4.0.0" @@ -2265,40 +2330,40 @@ jest-runtime@^29.6.4: collect-v8-coverage "^1.0.0" glob "^7.1.3" graceful-fs "^4.2.9" - jest-haste-map "^29.6.4" - jest-message-util "^29.6.3" - jest-mock "^29.6.3" + jest-haste-map "^29.7.0" + jest-message-util "^29.7.0" + jest-mock "^29.7.0" jest-regex-util "^29.6.3" - jest-resolve "^29.6.4" - jest-snapshot "^29.6.4" - jest-util "^29.6.3" + jest-resolve "^29.7.0" + jest-snapshot "^29.7.0" + jest-util "^29.7.0" slash "^3.0.0" strip-bom "^4.0.0" -jest-snapshot@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.6.4.tgz#9833eb6b66ff1541c7fd8ceaa42d541f407b4876" - integrity sha512-VC1N8ED7+4uboUKGIDsbvNAZb6LakgIPgAF4RSpF13dN6YaMokfRqO+BaqK4zIh6X3JffgwbzuGqDEjHm/MrvA== +jest-snapshot@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-29.7.0.tgz#c2c574c3f51865da1bb329036778a69bf88a6be5" + integrity sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw== dependencies: "@babel/core" "^7.11.6" "@babel/generator" "^7.7.2" "@babel/plugin-syntax-jsx" "^7.7.2" "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/types" "^7.3.3" - "@jest/expect-utils" "^29.6.4" - "@jest/transform" "^29.6.4" + "@jest/expect-utils" "^29.7.0" + "@jest/transform" "^29.7.0" "@jest/types" "^29.6.3" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^29.6.4" + expect "^29.7.0" graceful-fs "^4.2.9" - jest-diff "^29.6.4" + jest-diff "^29.7.0" jest-get-type "^29.6.3" - jest-matcher-utils "^29.6.4" - jest-message-util "^29.6.3" - jest-util "^29.6.3" + jest-matcher-utils "^29.7.0" + jest-message-util "^29.7.0" + jest-util "^29.7.0" natural-compare "^1.4.0" - pretty-format "^29.6.3" + pretty-format "^29.7.0" semver "^7.5.3" jest-util@^29.0.0, jest-util@^29.6.3: @@ -2313,51 +2378,63 @@ jest-util@^29.0.0, jest-util@^29.6.3: graceful-fs "^4.2.9" picomatch "^2.2.3" -jest-validate@^29.6.3: - version "29.6.3" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.6.3.tgz#a75fca774cfb1c5758c70d035d30a1f9c2784b4d" - integrity sha512-e7KWZcAIX+2W1o3cHfnqpGajdCs1jSM3DkXjGeLSNmCazv1EeI1ggTeK5wdZhF+7N+g44JI2Od3veojoaumlfg== +jest-util@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" + integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== + dependencies: + "@jest/types" "^29.6.3" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-validate@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-29.7.0.tgz#7bf705511c64da591d46b15fce41400d52147d9c" + integrity sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw== dependencies: "@jest/types" "^29.6.3" camelcase "^6.2.0" chalk "^4.0.0" jest-get-type "^29.6.3" leven "^3.1.0" - pretty-format "^29.6.3" + pretty-format "^29.7.0" -jest-watcher@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.6.4.tgz#633eb515ae284aa67fd6831f1c9d1b534cf0e0ba" - integrity sha512-oqUWvx6+On04ShsT00Ir9T4/FvBeEh2M9PTubgITPxDa739p4hoQweWPRGyYeaojgT0xTpZKF0Y/rSY1UgMxvQ== +jest-watcher@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-29.7.0.tgz#7810d30d619c3a62093223ce6bb359ca1b28a2f2" + integrity sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g== dependencies: - "@jest/test-result" "^29.6.4" + "@jest/test-result" "^29.7.0" "@jest/types" "^29.6.3" "@types/node" "*" ansi-escapes "^4.2.1" chalk "^4.0.0" emittery "^0.13.1" - jest-util "^29.6.3" + jest-util "^29.7.0" string-length "^4.0.1" -jest-worker@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.6.4.tgz#f34279f4afc33c872b470d4af21b281ac616abd3" - integrity sha512-6dpvFV4WjcWbDVGgHTWo/aupl8/LbBx2NSKfiwqf79xC/yeJjKHT1+StcKy/2KTmW16hE68ccKVOtXf+WZGz7Q== +jest-worker@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.7.0.tgz#acad073acbbaeb7262bd5389e1bcf43e10058d4a" + integrity sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw== dependencies: "@types/node" "*" - jest-util "^29.6.3" + jest-util "^29.7.0" merge-stream "^2.0.0" supports-color "^8.0.0" -jest@^29.6.4: - version "29.6.4" - resolved "https://registry.yarnpkg.com/jest/-/jest-29.6.4.tgz#7c48e67a445ba264b778253b5d78d4ebc9d0a622" - integrity sha512-tEFhVQFF/bzoYV1YuGyzLPZ6vlPrdfvDmmAxudA1dLEuiztqg2Rkx20vkKY32xiDROcD2KXlgZ7Cu8RPeEHRKw== +jest@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-29.7.0.tgz#994676fc24177f088f1c5e3737f5697204ff2613" + integrity sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw== dependencies: - "@jest/core" "^29.6.4" + "@jest/core" "^29.7.0" "@jest/types" "^29.6.3" import-local "^3.0.2" - jest-cli "^29.6.4" + jest-cli "^29.7.0" js-tokens@^4.0.0: version "4.0.0" @@ -2732,6 +2809,15 @@ pretty-format@^29.0.0, pretty-format@^29.6.3: ansi-styles "^5.0.0" react-is "^18.0.0" +pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + prompts@^2.0.1, prompts@~2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -3096,10 +3182,10 @@ typedoc@^0.25.1: minimatch "^9.0.3" shiki "^0.14.1" -typescript@^4.9.5: - version "4.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a" - integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g== +typescript@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" + integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== update-browserslist-db@^1.0.11: version "1.0.11" From a5ea7443e6eea13768d00740547fe5da563bc20f Mon Sep 17 00:00:00 2001 From: Ronan-Yann Lorin Date: Mon, 18 Sep 2023 07:53:09 +0200 Subject: [PATCH 2/3] matching symbols test added --- src/api-next/api-next.ts | 39 ++++++-- src/api-next/common/item-list-update.ts | 3 - src/core/api-next/item-list-update.ts | 1 - src/core/api-next/subscription.ts | 21 +---- src/core/io/socket.ts | 2 +- .../unit/api-next/get-account-summary.test.ts | 75 +++++++++------- src/tests/unit/api/matching-symbols.test.ts | 89 +++++++++++++++++++ .../unit/api/order/reqAllOpenOrders.test.ts | 40 +++++---- 8 files changed, 189 insertions(+), 81 deletions(-) create mode 100644 src/tests/unit/api/matching-symbols.test.ts diff --git a/src/api-next/api-next.ts b/src/api-next/api-next.ts index bda26c31..eed11d03 100644 --- a/src/api-next/api-next.ts +++ b/src/api-next/api-next.ts @@ -437,7 +437,9 @@ export class IBApiNext { ], ]); - if (hasChanged) { + if (!subscription.endEventReceived) { + subscription.lastAllValue = cached; + } else if (hasChanged) { subscription.next({ all: cached, changed: accountSummaryUpdate, @@ -450,6 +452,25 @@ export class IBApiNext { } }; + /** accountSummaryEnd event handler */ + private readonly onAccountSummaryEnd = ( + subscriptions: Map>, + reqId: number, + ): void => { + // get the subscription + const subscription = subscriptions.get(reqId); + if (!subscription) { + return; + } + + // get latest value on cache + const cached = subscription.lastAllValue ?? new MutableAccountSummaries(); + + // sent data to subscribers + subscription.endEventReceived = true; + subscription.next({ all: cached }); + }; + /** * Create subscription to receive the account summaries of all linked accounts as presented in the TWS' Account Summary tab. * @@ -507,7 +528,10 @@ export class IBApiNext { (reqId) => { this.api.cancelAccountSummary(reqId); }, - [[EventName.accountSummary, this.onAccountSummary]], + [ + [EventName.accountSummary, this.onAccountSummary], + [EventName.accountSummaryEnd, this.onAccountSummaryEnd], + ], `${group}:${tags}`, ); } @@ -713,7 +737,12 @@ export class IBApiNext { accountName: string, ): void => { this.logger.debug(LOG_TAG, `onAccountDownloadEnd(${accountName})`); - // TODO finish implementation + // notify all subscribers + subscriptions.forEach((subscription) => { + const all: AccountUpdate = subscription.lastAllValue ?? {}; + subscription.endEventReceived = true; + subscription.next({ all }); + }); }; /** @@ -2426,10 +2455,6 @@ export class IBApiNext { all: lastAllValue, }; subscription.endEventReceived = true; - - // console.log("onScannerDataEnd", updated); - - // subscription.next(updated); subscription.next(updated); }; diff --git a/src/api-next/common/item-list-update.ts b/src/api-next/common/item-list-update.ts index bb2723a3..097338ae 100644 --- a/src/api-next/common/item-list-update.ts +++ b/src/api-next/common/item-list-update.ts @@ -5,9 +5,6 @@ export interface ItemListUpdate { /** All items with its latest values, as received by TWS. */ readonly all: T; - /** all value is set with all items (ie not still being built = End message received from TWS) */ - readonly allset?: boolean; - /** Items that have been added since last [[IBApiNextUpdate]]. */ readonly added?: T; diff --git a/src/core/api-next/item-list-update.ts b/src/core/api-next/item-list-update.ts index a702dfbc..412b5752 100644 --- a/src/core/api-next/item-list-update.ts +++ b/src/core/api-next/item-list-update.ts @@ -12,6 +12,5 @@ export class IBApiNextItemListUpdate implements ItemListUpdate { public readonly added?: T, public readonly changed?: T, public readonly removed?: T, - public readonly allset?: boolean, ) {} } diff --git a/src/core/api-next/subscription.ts b/src/core/api-next/subscription.ts index 7154bd50..cd0c0d8c 100644 --- a/src/core/api-next/subscription.ts +++ b/src/core/api-next/subscription.ts @@ -4,11 +4,6 @@ import { IBApiNext, IBApiNextError, ItemListUpdate } from "../../api-next"; import { ConnectionState } from "../../api-next/common/connection-state"; import { IBApiNextItemListUpdate } from "./item-list-update"; -export type IBApiNextItemListUpdateMinimal = Omit< - IBApiNextItemListUpdate, - "added" | "changed" | "removed" ->; - /** * @internal * @@ -56,8 +51,8 @@ export class IBApiNextSubscription { /** The [[Subscription]] on the connection state. */ private connectionState$?: Subscription; - /** true when the end-event on an enumeration request has been received, false otherwise. */ - private _endEventReceived = false; + /** @internal True when the end-event on an enumeration request has been received, false otherwise. */ + public endEventReceived = false; /** Get the last 'all' value as send to subscribers. */ get lastAllValue(): T | undefined { @@ -69,16 +64,6 @@ export class IBApiNextSubscription { this._lastAllValue = value; } - /** @internal Get the end event flag. For internal use only. */ - get endEventReceived(): boolean { - return this._endEventReceived; - } - - /** @internal Set the end event flag seen. For internal use only. */ - set endEventReceived(value: boolean) { - this._endEventReceived = value; - } - /** * Send the next value to subscribers. * @@ -102,7 +87,7 @@ export class IBApiNextSubscription { */ error(error: IBApiNextError): void { delete this._lastAllValue; - this._endEventReceived = false; + this.endEventReceived = false; this.hasError = true; this.subject.error(error); this.cancelTwsSubscription(); diff --git a/src/core/io/socket.ts b/src/core/io/socket.ts index 9753a7df..316cd1f5 100644 --- a/src/core/io/socket.ts +++ b/src/core/io/socket.ts @@ -32,7 +32,7 @@ const EOL = "\0"; * @hidden * add a delay after connect before sending commands */ -const CONNECT_DELAY = 600; +// const CONNECT_DELAY = 600; /** * @internal diff --git a/src/tests/unit/api-next/get-account-summary.test.ts b/src/tests/unit/api-next/get-account-summary.test.ts index 32778a5e..44e1d093 100644 --- a/src/tests/unit/api-next/get-account-summary.test.ts +++ b/src/tests/unit/api-next/get-account-summary.test.ts @@ -3,12 +3,12 @@ */ import { take } from "rxjs/operators"; -import { IBApi, IBApiNext, IBApiNextError, EventName } from "../../.."; +import { EventName, IBApi, IBApiNext, IBApiNextError } from "../../.."; describe("RxJS Wrapper: getAccountSummary()", () => { test("Error Event", (done) => { const apiNext = new IBApiNext(); - const api = ((apiNext as unknown) as Record).api as IBApi; + const api = (apiNext as unknown as Record).api as IBApi; // emit a error event and verify RxJS result @@ -32,7 +32,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { test("Update multicast", (done) => { const apiNext = new IBApiNext(); - const api = ((apiNext as unknown) as Record).api as IBApi; + const api = (apiNext as unknown as Record).api as IBApi; // testing values @@ -55,7 +55,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { next: (update) => { expect( update.all.get(accountId1)?.get("NetLiquidation")?.get(currency) - ?.value + ?.value, ).toEqual(testValueReqId1); receivedNetLiquidation++; if (receivedNetLiquidation == 2 && receivedTotalCashValue == 2) { @@ -74,7 +74,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { next: (update) => { expect( update.all.get(accountId1)?.get("NetLiquidation")?.get(currency) - ?.value + ?.value, ).toEqual(testValueReqId1); receivedNetLiquidation++; if (receivedNetLiquidation == 2 && receivedTotalCashValue == 2) { @@ -95,7 +95,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { next: (update) => { expect( update.all.get(accountId2)?.get("TotalCashValue")?.get(currency) - ?.value + ?.value, ).toEqual(testValueReqId1); receivedTotalCashValue++; if (receivedNetLiquidation == 2 && receivedTotalCashValue == 2) { @@ -114,7 +114,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { next: (update) => { expect( update.all.get(accountId2)?.get("TotalCashValue")?.get(currency) - ?.value + ?.value, ).toEqual(testValueReqId1); receivedTotalCashValue++; if (receivedNetLiquidation == 2 && receivedTotalCashValue == 2) { @@ -132,8 +132,9 @@ describe("RxJS Wrapper: getAccountSummary()", () => { accountId1, "NetLiquidation", testValueReqId1, - currency + currency, ); + api.emit(EventName.accountSummaryEnd, 1); api.emit( EventName.accountSummary, @@ -141,13 +142,14 @@ describe("RxJS Wrapper: getAccountSummary()", () => { accountId2, "TotalCashValue", testValueReqId1, - currency + currency, ); + api.emit(EventName.accountSummaryEnd, 2); }); test("Aggregate into all", (done) => { const apiNext = new IBApiNext(); - const api = ((apiNext as unknown) as Record).api as IBApi; + const api = (apiNext as unknown as Record).api as IBApi; // testing values @@ -175,38 +177,44 @@ describe("RxJS Wrapper: getAccountSummary()", () => { update.all.forEach((tagValues) => tagValues.forEach((currencyValues) => { totalValuesCount += currencyValues.size; - }) + }), ); switch (totalValuesCount) { case 6: expect( - update.all.get(accountId2)?.get(tagName2)?.get(currency2)?.value + update.all.get(accountId2)?.get(tagName2)?.get(currency2) + ?.value, ).toEqual(currency2Value); // no break by intention case 5: expect( - update.all.get(accountId2)?.get(tagName2)?.get(currency1)?.value + update.all.get(accountId2)?.get(tagName2)?.get(currency1) + ?.value, ).toEqual(currency1Value); // no break by intention case 4: expect( - update.all.get(accountId2)?.get(tagName1)?.get(currency2)?.value + update.all.get(accountId2)?.get(tagName1)?.get(currency2) + ?.value, ).toEqual(currency2Value); // no break by intention case 3: expect( - update.all.get(accountId2)?.get(tagName1)?.get(currency1)?.value + update.all.get(accountId2)?.get(tagName1)?.get(currency1) + ?.value, ).toEqual(currency1Value); // no break by intention case 2: expect( - update.all.get(accountId1)?.get(tagName1)?.get(currency2)?.value + update.all.get(accountId1)?.get(tagName1)?.get(currency2) + ?.value, ).toEqual(currency2Value); // no break by intention case 1: expect( - update.all.get(accountId1)?.get(tagName1)?.get(currency1)?.value + update.all.get(accountId1)?.get(tagName1)?.get(currency1) + ?.value, ).toEqual(currency1Value); break; } @@ -227,8 +235,9 @@ describe("RxJS Wrapper: getAccountSummary()", () => { accountId1, tagName1, currency1Value, - currency1 + currency1, ); + api.emit(EventName.accountSummaryEnd, 1); api.emit( EventName.accountSummary, @@ -236,7 +245,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { accountId1, tagName1, currency2Value, - currency2 + currency2, ); api.emit( @@ -245,7 +254,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { accountId2, tagName1, currency1Value, - currency1 + currency1, ); api.emit( @@ -254,7 +263,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { accountId2, tagName1, currency2Value, - currency2 + currency2, ); api.emit( @@ -263,7 +272,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { accountId2, tagName2, currency1Value, - currency1 + currency1, ); api.emit( @@ -272,13 +281,13 @@ describe("RxJS Wrapper: getAccountSummary()", () => { accountId2, tagName2, currency2Value, - currency2 + currency2, ); }); test("Detected changes", (done) => { const apiNext = new IBApiNext(); - const api = ((apiNext as unknown) as Record).api as IBApi; + const api = (apiNext as unknown as Record).api as IBApi; // testing values @@ -297,11 +306,11 @@ describe("RxJS Wrapper: getAccountSummary()", () => { next: (update) => { if (update.added?.size) { expect( - update.added.get(accountId)?.get(tagName)?.get(currency)?.value + update.added.get(accountId)?.get(tagName)?.get(currency)?.value, ).toEqual(testValue1); } else if (update.changed?.size) { expect( - update.changed.get(accountId)?.get(tagName)?.get(currency)?.value + update.changed.get(accountId)?.get(tagName)?.get(currency)?.value, ).toEqual(testValue2); done(); } else { @@ -319,8 +328,9 @@ describe("RxJS Wrapper: getAccountSummary()", () => { accountId, tagName, testValue1, - currency + currency, ); + api.emit(EventName.accountSummaryEnd, 1); api.emit( EventName.accountSummary, @@ -328,7 +338,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { accountId, tagName, testValue2, - currency + currency, ); }); @@ -336,7 +346,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { // create IBApiNext and reqId counter const apiNext = new IBApiNext(); - const api = ((apiNext as unknown) as Record).api as IBApi; + const api = (apiNext as unknown as Record).api as IBApi; // testing values @@ -353,7 +363,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { .subscribe({ next: (update) => { expect( - update.added.get(accountId)?.get(tagName)?.get(currency)?.value + update.added.get(accountId)?.get(tagName)?.get(currency)?.value, ).toEqual(testValue); apiNext @@ -364,7 +374,7 @@ describe("RxJS Wrapper: getAccountSummary()", () => { next: (update) => { expect( update.added.get(accountId)?.get(tagName)?.get(currency) - ?.value + ?.value, ).toEqual(testValue); done(); }, @@ -384,7 +394,8 @@ describe("RxJS Wrapper: getAccountSummary()", () => { accountId, tagName, testValue, - currency + currency, ); + api.emit(EventName.accountSummaryEnd, 1); }); }); diff --git a/src/tests/unit/api/matching-symbols.test.ts b/src/tests/unit/api/matching-symbols.test.ts new file mode 100644 index 00000000..caf492e2 --- /dev/null +++ b/src/tests/unit/api/matching-symbols.test.ts @@ -0,0 +1,89 @@ +import { IBApi } from "../../../api/api"; +import ContractDescription from "../../../api/contract/contractDescription"; +import { EventName } from "../../../api/data/enum/event-name"; +import configuration from "../../../common/configuration"; + +describe("IBApi reqMatchingSymbols Tests", () => { + jest.setTimeout(5000); + + let ib: IBApi; + const clientId = Math.floor(Math.random() * 32766) + 1; // ensure unique client + + beforeEach(() => { + ib = new IBApi({ + host: configuration.ib_host, + port: configuration.ib_port, + clientId, + }); + }); + + afterEach(() => { + if (ib) { + ib.disconnect(); + ib = undefined; + } + }); + + test("SPY", (done) => { + let tickerId: number; + ib.once(EventName.nextValidId, (reqId) => { + tickerId = reqId; + ib.reqMatchingSymbols(reqId, "SPY"); + }) + .on(EventName.disconnected, () => { + done(); + }) + .on( + EventName.symbolSamples, + (reqId, contractDescriptions: ContractDescription[]) => { + expect(reqId).toEqual(tickerId); + expect(contractDescriptions[0].contract.symbol).toEqual("SPY"); + ib.disconnect(); + }, + ); + + ib.connect(); + }); + + test("META", (done) => { + let tickerId: number; + ib.once(EventName.nextValidId, (reqId) => { + tickerId = reqId; + ib.reqMatchingSymbols(reqId, "META"); + }) + .on(EventName.disconnected, () => { + done(); + }) + .on( + EventName.symbolSamples, + (reqId, contractDescriptions: ContractDescription[]) => { + expect(reqId).toEqual(tickerId); + expect(contractDescriptions[0].contract.symbol).toEqual("META"); + ib.disconnect(); + }, + ); + + ib.connect(); + }); + + test("AMC", (done) => { + let tickerId: number; + ib.once(EventName.nextValidId, (reqId) => { + tickerId = reqId; + ib.reqMatchingSymbols(reqId, "AMC"); + }) + .on(EventName.disconnected, () => { + done(); + }) + .on( + EventName.symbolSamples, + (reqId, contractDescriptions: ContractDescription[]) => { + expect(reqId).toEqual(tickerId); + expect(contractDescriptions[0].contract.symbol).toEqual("AMC"); + ib.disconnect(); + }, + ); + + ib.connect(); + }); +}); diff --git a/src/tests/unit/api/order/reqAllOpenOrders.test.ts b/src/tests/unit/api/order/reqAllOpenOrders.test.ts index 16242290..f8c0a173 100644 --- a/src/tests/unit/api/order/reqAllOpenOrders.test.ts +++ b/src/tests/unit/api/order/reqAllOpenOrders.test.ts @@ -10,14 +10,28 @@ const TEST_SERVER_POST = configuration.ib_port; describe("RequestAllOpenOrders", () => { jest.setTimeout(10000); - let _clientId = Math.floor(Math.random() * 32766) + 1; // ensure unique client - it("Test reqAllOpenOrders", (done) => { - const ib = new IBApi({ - host: TEST_SERVER_HOST, - port: TEST_SERVER_POST, + let ib: IBApi; + let clientId = Math.floor(Math.random() * 32766) + 1; // ensure unique client + + beforeEach(() => { + ib = new IBApi({ + host: configuration.ib_host, + port: configuration.ib_port, + clientId, }); + // logger.info("IBApi created"); + }); + + afterEach(() => { + if (ib) { + ib.disconnect(); + ib = undefined; + } + // logger.info("IBApi disconnected"); + }); + it("Test reqAllOpenOrders", (done) => { let received = false; ib.on(EventName.openOrder, (orderId, contract, order, orderState) => { @@ -26,28 +40,16 @@ describe("RequestAllOpenOrders", () => { // expect(orderId).toBeTruthy(); We sometimes get zeros }) .on(EventName.openOrderEnd, () => { - // logger.info("openOrderEnd message received"); - received = true; - // done ib.disconnect(); - }) - .on(EventName.connected, () => { - // logger.info("connected"); - ib.reqIds(); - }) - .on(EventName.disconnected, () => { - if (received) done(); - else done("We didn't received acknowledge"); + done(); }) .on(EventName.error, (err: Error, code: ErrorCode, id: number) => { done(`${err.message} - code: ${code} - id: ${id}`); }) .once(EventName.nextValidId, (orderId: number) => { - // logger.info(`nextValidId: ${orderId}, requesting orders`); - ib.reqAllOpenOrders(); }); - ib.connect(_clientId++); + ib.connect(); }); }); From a0ec54f615b4571f43669e1d7606a5db16fcfb22 Mon Sep 17 00:00:00 2001 From: Ronan-Yann Lorin Date: Mon, 18 Sep 2023 08:01:08 +0200 Subject: [PATCH 3/3] lint fix --- src/tests/unit/api/order/reqAllOpenOrders.test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/tests/unit/api/order/reqAllOpenOrders.test.ts b/src/tests/unit/api/order/reqAllOpenOrders.test.ts index f8c0a173..c9e652d5 100644 --- a/src/tests/unit/api/order/reqAllOpenOrders.test.ts +++ b/src/tests/unit/api/order/reqAllOpenOrders.test.ts @@ -12,7 +12,7 @@ describe("RequestAllOpenOrders", () => { jest.setTimeout(10000); let ib: IBApi; - let clientId = Math.floor(Math.random() * 32766) + 1; // ensure unique client + const clientId = Math.floor(Math.random() * 32766) + 1; // ensure unique client beforeEach(() => { ib = new IBApi({ @@ -32,8 +32,6 @@ describe("RequestAllOpenOrders", () => { }); it("Test reqAllOpenOrders", (done) => { - let received = false; - ib.on(EventName.openOrder, (orderId, contract, order, orderState) => { // logger.info("openOrder message received"); // todo add proper verification code here