diff --git a/CHANGELOG.md b/CHANGELOG.md index 949399a14e..ca3745a6fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,31 @@ ## vNext (TBD) ### Deprecations -* None +* The callback for `realm.syncSession.addProgressNotification` will only take a single argument in the future: `estimate` (which supports both partition based and flexible sync). The old callback functionality is deprecated and will be removed. The estimate is roughly equivalent to an estimated value of `transferred / transferable` in the deprecated partition-based sync callback. ([#6256](https://github.com/realm/realm-js/issues/6256)) +```ts +/** New callback which supports both flexible and partition-based sync */ +realm.syncSession.addProgressNotification( + Realm.ProgressDirection.Upload, + ProgressMode.ReportIndefinitely, + (estimate) => console.log(`progress estimate: ${estimate}/1.0`), +); +/** @deprecated */ +realm.syncSession.addProgressNotification( + Realm.ProgressDirection.Upload, + ProgressMode.ReportIndefinitely, + (transferred, transferable) => console.log(`progress: ${(transferred / transferable)}/1.0`), +); +``` ### Enhancements -* None +* Added progress notifications support for flexible sync using a new callback argument. ([#6256](https://github.com/realm/realm-js/issues/6256)) +```ts +realm.syncSession.addProgressNotification( + Realm.ProgressDirection.Upload, + ProgressMode.ReportIndefinitely, + (estimate) => console.log(`progress: ${estimate}/1.0`) +); +``` ### Fixed * ([#????](https://github.com/realm/realm-js/issues/????), since v?.?.?) diff --git a/integration-tests/tests/package.json b/integration-tests/tests/package.json index f551f20266..aa14b78d52 100644 --- a/integration-tests/tests/package.json +++ b/integration-tests/tests/package.json @@ -84,6 +84,9 @@ "@types/chai-as-promised": "^7.1.5", "@types/jsrsasign": "^10.5.4", "@types/mocha": "^10.0.0", + "@types/sinon": "9.0.5", + "@types/sinon-chai": "3.2.12", + "assert": "^2.1.0", "mocha": "^10.1.0", "nyc": "^15.1.0", "platform": "^1.3.6", @@ -94,7 +97,9 @@ "chai": "4.3.6", "chai-as-promised": "^7.1.1", "jsrsasign": "^11.0.0", - "node-fetch": "^3.3.2" + "node-fetch": "^3.3.2", + "sinon": "9.2.4", + "sinon-chai": "3.7.0" }, "files": [ "/src" diff --git a/integration-tests/tests/src/setup-globals.ts b/integration-tests/tests/src/setup-globals.ts index d7a4e6256e..8334b0ffa5 100644 --- a/integration-tests/tests/src/setup-globals.ts +++ b/integration-tests/tests/src/setup-globals.ts @@ -39,6 +39,9 @@ import chai from "chai"; // See https://stackoverflow.com/a/45882252 chai.config.truncateThreshold = 0; +import sinonChai from "sinon-chai"; +chai.use(sinonChai); + import chaiAsPromised from "chai-as-promised"; chai.use(chaiAsPromised); diff --git a/integration-tests/tests/src/tests/sync/flexible.ts b/integration-tests/tests/src/tests/sync/flexible.ts index fe97d1b20a..6215bf2368 100644 --- a/integration-tests/tests/src/tests/sync/flexible.ts +++ b/integration-tests/tests/src/tests/sync/flexible.ts @@ -39,6 +39,9 @@ import Realm, { SubscriptionSetState, CompensatingWriteError, WaitForSync, + ProgressMode, + Credentials, + OpenRealmBehaviorType, } from "realm"; import { authenticateUserBefore, importAppBefore, openRealmBeforeEach } from "../../hooks"; @@ -47,6 +50,7 @@ import { expectClientResetError } from "../../utils/expect-sync-error"; import { createSyncConfig } from "../../utils/open-realm"; import { createPromiseHandle } from "../../utils/promise-handle"; import { buildAppConfig } from "../../utils/build-app-config"; +import { spy } from "sinon"; export const PersonSchema: Realm.ObjectSchema = { name: "Person", @@ -57,6 +61,7 @@ export const PersonSchema: Realm.ObjectSchema = { name: "string", friends: "Person[]", nonQueryable: "string?", + data: "data?", }, }; @@ -66,6 +71,7 @@ export class Person extends Realm.Object { age!: number; friends!: Realm.List; dogs!: Realm.Collection; + data?: Realm.Types.Data; static schema: Realm.ObjectSchema = PersonSchema; } @@ -2075,4 +2081,400 @@ describe("Flexible sync", function () { }); }); }); + + describe("Progress notification", function () { + this.timeout(5000); + before(async function (this: UserContext) { + // TODO: Investigate this. + // Use a new user for this test suite as not doing so causes some session issues in other tests + this.user = await this.app.logIn(Credentials.anonymous(false)); + }); + beforeEach(async function (this: RealmContext & UserContext) { + // @ts-expect-error Using an internal API + this.realm = new Realm({ + schema: [Person, Dog], + sync: { + flexible: true, + user: this.user, + _sessionStopPolicy: SessionStopPolicy.Immediately, + }, + }); + }); + + it("only estimate callback is allowed", async function (this: RealmContext) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function + const callback = (estimate: number) => {}; + this.realm.syncSession?.addProgressNotification( + Realm.ProgressDirection.Download, + Realm.ProgressMode.ForCurrentlyOutstandingWork, + callback, + ); + }); + + it("old callback style is not allowed", async function (this: RealmContext) { + // eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-empty-function + const callback = spy((transferable: number, transferred: number) => {}); + expect(() => { + this.realm.syncSession?.addProgressNotification( + Realm.ProgressDirection.Download, + Realm.ProgressMode.ForCurrentlyOutstandingWork, + callback, + ); + }).to.throw(); + + expect(callback).not.called; + }); + + describe("with ProgressMode.ReportIndefinitely", function () { + describe(`with ProgressDirection.Upload`, function () { + it("should not call callback when there is nothing to upload", async function (this: RealmContext) { + const realm = this.realm; + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars + const callback = spy((estimate: number) => {}); + + realm.syncSession?.addProgressNotification( + Realm.ProgressDirection.Upload, + ProgressMode.ReportIndefinitely, + callback, + ); + + expect(callback).not.called; + }); + + it("should be called multiple times with different values during uploads", async function (this: RealmContext) { + const realm = this.realm; + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars + const callback = spy((estimate: number) => {}); + + realm.syncSession?.addProgressNotification( + Realm.ProgressDirection.Upload, + Realm.ProgressMode.ReportIndefinitely, + callback, + ); + + await this.realm.syncSession?.uploadAllLocalChanges(); + await this.realm.syncSession?.downloadAllServerChanges(); + + // TODO: This callback should not be called at this stage but seems flakey + // and gets called with 1.0 at times, likely because of a race condition. + expect(callback.notCalled || callback.calledWith(1.0)).is.true; + const subscription = await realm.objects(Person).subscribe(); + + realm.write(() => { + realm.create(Person, { + _id: new BSON.ObjectId(), + name: "Heavy", + age: 36, + data: new ArrayBuffer(1_000_000), + }); + }); + + await realm.syncSession?.uploadAllLocalChanges(); + subscription.unsubscribe(); + + // TODO: Find a way to fix + // There should be at least one point where the progress is not yet finished. + // expect(callback.args.find(([estimate]) => estimate < 1)).to.not.be.undefined; + + expect(callback.withArgs(1.0)).called; + }); + + it("should not run after it has been removed", async function (this: RealmContext) { + const realm = this.realm; + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars + const callback = spy((estimate: number) => {}); + + realm.syncSession?.addProgressNotification( + Realm.ProgressDirection.Upload, + Realm.ProgressMode.ReportIndefinitely, + callback, + ); + + await this.realm.syncSession?.uploadAllLocalChanges(); + await this.realm.syncSession?.downloadAllServerChanges(); + + // TODO: This callback should not be called at this stage but seems flakey + // and gets called with 1.0 at times, likely because of a race condition. + expect(callback.notCalled || callback.calledWith(1.0)).is.true; + + realm.objects(Person).subscribe(); + + realm.write(() => { + realm.create(Person, { + _id: new BSON.ObjectId(), + name: "Heavy", + age: 36, + data: new ArrayBuffer(1_000_000), + }); + }); + + await realm.syncSession?.uploadAllLocalChanges(); + await realm.syncSession?.downloadAllServerChanges(); + const oldCallCount = callback.callCount; + expect(callback.callCount).to.be.greaterThanOrEqual(2); + + realm.syncSession?.removeProgressNotification(callback); + + realm.write(() => { + realm.create(Person, { + _id: new BSON.ObjectId(), + name: "Heavy", + age: 36, + data: new ArrayBuffer(1_000_000), + }); + }); + + await realm.syncSession?.uploadAllLocalChanges(); + + expect(callback.callCount).to.be.equal(oldCallCount); + }); + }); + + describe(`with ProgressDirection.Download`, function () { + it("should not call the callback when there is nothing to download", async function (this: RealmContext) { + const realm = this.realm; + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars + const callback = spy((estimate: number) => {}); + + realm.syncSession?.addProgressNotification( + Realm.ProgressDirection.Download, + ProgressMode.ReportIndefinitely, + callback, + ); + + await this.realm.syncSession?.uploadAllLocalChanges(); + await this.realm.syncSession?.downloadAllServerChanges(); + + // TODO: This callback should not be called at this stage but seems flakey + // and gets called with 1.0 at times, likely because of a race condition. + expect(callback.notCalled || callback.calledWith(1.0)).is.true; + }); + + it("should be called multiple times with different values during downloads", async function (this: RealmContext & + AppContext) { + const realm = this.realm; + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars + const callback = spy((estimate: number) => {}); + const realm2 = await Realm.open({ + schema: [Person, Dog], + sync: { + flexible: true, + user: await this.app.logIn(Credentials.anonymous(false)), + newRealmFileBehavior: { + type: OpenRealmBehaviorType.OpenImmediately, + }, + }, + }); + + realm2.syncSession?.addProgressNotification( + Realm.ProgressDirection.Download, + Realm.ProgressMode.ReportIndefinitely, + callback, + ); + + const subscription = await realm.objects(Person).subscribe(); + + realm.write(() => { + realm.create(Person, { + _id: new BSON.ObjectId(), + name: "Heavy", + age: 36, + data: new ArrayBuffer(1_000_000), + }); + }); + + await realm.syncSession?.uploadAllLocalChanges(); + const subscription2 = await realm2.objects(Person).subscribe(); + await realm2.syncSession?.downloadAllServerChanges(); + + expect(callback.args.find(([estimate]) => estimate < 1)).to.not.be.undefined; + expect(callback.withArgs(1.0).callCount).is.greaterThanOrEqual(2); + + subscription.unsubscribe(); + subscription2.unsubscribe(); + realm2.close(); + }); + + it("should not run after it has been removed", async function (this: RealmContext) { + const realm = this.realm; + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars + const callback = spy((estimate: number) => {}); + const realm2 = await Realm.open({ + schema: [Person, Dog], + sync: { + flexible: true, + user: await this.app.logIn(Credentials.anonymous(false)), + newRealmFileBehavior: { + type: OpenRealmBehaviorType.OpenImmediately, + }, + }, + }); + + realm2.syncSession?.addProgressNotification( + Realm.ProgressDirection.Download, + Realm.ProgressMode.ReportIndefinitely, + callback, + ); + + const subscription = await realm.objects(Person).subscribe(); + + realm.write(() => { + realm.create(Person, { + _id: new BSON.ObjectId(), + name: "Heavy", + age: 36, + data: new ArrayBuffer(1_000_000), + }); + }); + + const subscription2 = await realm2.objects(Person).subscribe(); + await realm.syncSession?.uploadAllLocalChanges(); + await realm2.syncSession?.downloadAllServerChanges(); + + expect(callback.args.find(([estimate]) => estimate < 1)).to.not.be.undefined; + expect(callback.withArgs(1.0).callCount).is.greaterThanOrEqual(2); + const oldCallCount = callback.callCount; + + realm2.syncSession?.removeProgressNotification(callback); + + realm.write(() => { + realm.create(Person, { + _id: new BSON.ObjectId(), + name: "Heavy", + age: 36, + data: new ArrayBuffer(1_000_000), + }); + }); + + await realm.syncSession?.uploadAllLocalChanges(); + await realm2.syncSession?.downloadAllServerChanges(); + + expect(callback).has.callCount(oldCallCount); + + subscription.unsubscribe(); + subscription2.unsubscribe(); + realm2.close(); + }); + }); + }); + + describe("with ProgressMode.ForCurrentlyOutstandingWork", () => { + describe(`with ProgressDirection.Upload`, function () { + it("should not call callback when there is nothing to upload", async function (this: RealmContext) { + const realm = this.realm; + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars + const callback = spy((estimate: number) => {}); + + await realm.syncSession?.uploadAllLocalChanges(); + + realm.syncSession?.addProgressNotification( + Realm.ProgressDirection.Upload, + ProgressMode.ForCurrentlyOutstandingWork, + callback, + ); + + expect(callback).not.called; + }); + + it("should be called multiple times with different values during uploads", async function (this: RealmContext) { + const realm = this.realm; + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars + const callback = spy((estimate: number) => {}); + + realm.syncSession?.addProgressNotification( + Realm.ProgressDirection.Upload, + Realm.ProgressMode.ForCurrentlyOutstandingWork, + callback, + ); + + const subscription = await realm.objects(Person).subscribe(); + + realm.write(() => { + realm.create(Person, { + _id: new BSON.ObjectId(), + name: "Heavy", + age: 36, + data: new ArrayBuffer(1_000_000), + }); + }); + + await realm.syncSession?.uploadAllLocalChanges(); + + // TODO: Find a way to fix + // There should be at least one point where the progress is not yet finished. + // expect(callback.args.find(([estimate]) => estimate < 1)).to.not.be.undefined; + + expect(callback.withArgs(1.0)).called; + + subscription.unsubscribe(); + }); + }); + + describe(`with ProgressDirection.Download`, function () { + it("should not call callback when there is nothing to download", async function (this: RealmContext) { + const realm = this.realm; + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars + const callback = spy((estimate: number) => {}); + + await realm.syncSession?.downloadAllServerChanges(); + + realm.syncSession?.addProgressNotification( + Realm.ProgressDirection.Download, + ProgressMode.ForCurrentlyOutstandingWork, + callback, + ); + + expect(callback).not.called; + }); + + it("should be called multiple times with different values during downloads", async function (this: RealmContext & + AppContext) { + const realm = this.realm; + // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-unused-vars + const callback = spy((estimate: number) => {}); + const realm2 = await Realm.open({ + schema: [Person, Dog], + sync: { + flexible: true, + user: await this.app.logIn(Credentials.anonymous(false)), + newRealmFileBehavior: { + type: OpenRealmBehaviorType.OpenImmediately, + }, + }, + }); + + const subscription = await realm.objects(Person).subscribe(); + + realm.write(() => { + realm.create(Person, { + _id: new BSON.ObjectId(), + name: "Heavy", + age: 36, + data: new ArrayBuffer(1_000_000), + }); + }); + + await realm.syncSession?.uploadAllLocalChanges(); + await realm2.objects(Person).subscribe(); + await realm2.syncSession?.downloadAllServerChanges(); + + // At this point there is no other work. + realm2.syncSession?.addProgressNotification( + Realm.ProgressDirection.Download, + Realm.ProgressMode.ForCurrentlyOutstandingWork, + callback, + ); + + // TODO: Doesn't work + // There should be at least one point where the progress is not yet finished. + // expect(callback.args.find(([estimate]) => estimate < 1)).to.not.be.undefined; + + expect(callback.withArgs(1.0)).calledOnce; + realm2.close(); + + subscription.unsubscribe(); + }); + }); + }); + }); }); diff --git a/integration-tests/tests/src/tests/sync/sync-session.ts b/integration-tests/tests/src/tests/sync/sync-session.ts index ded450008d..a9d6f4df13 100644 --- a/integration-tests/tests/src/tests/sync/sync-session.ts +++ b/integration-tests/tests/src/tests/sync/sync-session.ts @@ -22,8 +22,9 @@ import { authenticateUserBefore, importAppBefore, openRealmBefore } from "../../ import { DogSchema } from "../../schemas/person-and-dog-with-object-ids"; import { getRegisteredEmailPassCredentials } from "../../utils/credentials"; import { generatePartition } from "../../utils/generators"; -import { sleep, throwAfterTimeout } from "../../utils/sleep"; +import { sleep } from "../../utils/sleep"; import { buildAppConfig } from "../../utils/build-app-config"; +import { spy } from "sinon"; const DogForSyncSchema: Realm.ObjectSchema = { name: "Dog", @@ -286,16 +287,14 @@ describe("SessionTest", () => { describe("progress notification", () => { afterEach(() => Realm.clearTestState()); it("is called", async function (this: AppContext) { + this.timeout(5000); const partition = generatePartition(); const { config } = await getSyncConfWithUser(this.app, partition); - let progressCalled = false; - await Promise.race([ - Realm.open(config).progress(() => { - progressCalled = true; - }), - throwAfterTimeout(5000), - ]); - expect(progressCalled).to.be.true; + + const progressCallback = spy(); + await Realm.open(config).progress(progressCallback); + + expect(progressCallback).called; }); it("removing progress notification does not invoke callback again", async function (this: AppContext) { @@ -339,8 +338,8 @@ describe("SessionTest", () => { realm.syncSession?.addProgressNotification("upload", "reportIndefinitely", progressCallback); writeDataFunc(); }); - await realm.close(); - user.logOut(); + realm.close(); + await user.logOut(); }); }); diff --git a/package-lock.json b/package-lock.json index 960e9fc2b8..f7fc9a13a7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -429,7 +429,9 @@ "chai": "4.3.6", "chai-as-promised": "^7.1.1", "jsrsasign": "^11.0.0", - "node-fetch": "^3.3.2" + "node-fetch": "^3.3.2", + "sinon": "9.2.4", + "sinon-chai": "3.7.0" }, "devDependencies": { "@realm/app-importer": "*", @@ -439,6 +441,9 @@ "@types/chai-as-promised": "^7.1.5", "@types/jsrsasign": "^10.5.4", "@types/mocha": "^10.0.0", + "@types/sinon": "9.0.5", + "@types/sinon-chai": "3.2.12", + "assert": "^2.1.0", "mocha": "^10.1.0", "nyc": "^15.1.0", "platform": "^1.3.6", @@ -454,6 +459,15 @@ "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", "dev": true }, + "integration-tests/tests/node_modules/@types/sinon": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-9.0.5.tgz", + "integrity": "sha512-4CnkGdM/5/FXDGqL32JQ1ttVrGvhOoesLLF7VnTh4KdjK5N5VQOtxaylFqqTjnHx55MnD9O02Nbk5c1ELC8wlQ==", + "dev": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, "integration-tests/tests/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -2835,7 +2849,6 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/cst-dts-gen/-/cst-dts-gen-10.5.0.tgz", "integrity": "sha512-lhmC/FyqQ2o7pGK4Om+hzuDrm9rhFYIJ/AXoQBeongmn870Xeb0L6oGEiuR8nohFNL5sMaQEJWCxr1oIVIVXrw==", - "dev": true, "dependencies": { "@chevrotain/gast": "10.5.0", "@chevrotain/types": "10.5.0", @@ -2846,7 +2859,6 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/gast/-/gast-10.5.0.tgz", "integrity": "sha512-pXdMJ9XeDAbgOWKuD1Fldz4ieCs6+nLNmyVhe2gZVqoO7v8HXuHYs5OV2EzUtbuai37TlOAQHrTDvxMnvMJz3A==", - "dev": true, "dependencies": { "@chevrotain/types": "10.5.0", "lodash": "4.17.21" @@ -2855,20 +2867,17 @@ "node_modules/@chevrotain/types": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/types/-/types-10.5.0.tgz", - "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==", - "dev": true + "integrity": "sha512-f1MAia0x/pAVPWH/T73BJVyO2XU5tI4/iE7cnxb7tqdNTNhQI3Uq3XkqcoteTmD4t1aM0LbHCJOhgIDn07kl2A==" }, "node_modules/@chevrotain/utils": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/@chevrotain/utils/-/utils-10.5.0.tgz", - "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==", - "dev": true + "integrity": "sha512-hBzuU5+JjB2cqNZyszkDHZgOSrUUT8V3dhgRl8Q9Gp6dAj/H5+KILGjbhDpc3Iy9qmqlm/akuOI2ut9VUtzJxQ==" }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -2880,7 +2889,6 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -6183,6 +6191,29 @@ "@sinonjs/commons": "^3.0.0" } }, + "node_modules/@sinonjs/samsam": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz", + "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==", + "dependencies": { + "@sinonjs/commons": "^1.6.0", + "lodash.get": "^4.4.2", + "type-detect": "^4.0.8" + } + }, + "node_modules/@sinonjs/samsam/node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.2.tgz", + "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==" + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -6414,26 +6445,22 @@ "node_modules/@tsconfig/node10": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "dev": true + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==" }, "node_modules/@tsconfig/node18": { "version": "18.2.2", @@ -6867,6 +6894,31 @@ "@types/node": "*" } }, + "node_modules/@types/sinon": { + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", + "integrity": "sha512-j3uovdn8ewky9kRBG19bOwaZbexJu/XjtkHyjvUgt4xfPFz18dcORIMqnYh66Fx3Powhcr85NT5+er3+oViapw==", + "dev": true, + "dependencies": { + "@types/sinonjs__fake-timers": "*" + } + }, + "node_modules/@types/sinon-chai": { + "version": "3.2.12", + "resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.12.tgz", + "integrity": "sha512-9y0Gflk3b0+NhQZ/oxGtaAJDvRywCa5sIyaVnounqLvmf93yBF4EgIRspePtkMs3Tr844nCclYMlcCNmLCvjuQ==", + "dev": true, + "dependencies": { + "@types/chai": "*", + "@types/sinon": "*" + } + }, + "node_modules/@types/sinonjs__fake-timers": { + "version": "8.1.5", + "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.5.tgz", + "integrity": "sha512-mQkU2jY8jJEF7YHjHvsQO8+3ughTL1mcnn96igfhONmR+fUPSKIkefQYpSe8bsly2Ep7oQbn/6VG5/9/0qcArQ==", + "dev": true + }, "node_modules/@types/sockjs": { "version": "0.3.36", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz", @@ -8031,8 +8083,7 @@ "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" }, "node_modules/argparse": { "version": "2.0.1", @@ -8214,6 +8265,19 @@ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -9391,13 +9455,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", - "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.1", - "set-function-length": "^1.1.1" + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9445,7 +9514,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", - "dev": true, "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" @@ -9482,7 +9550,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", @@ -9565,7 +9632,6 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", - "dev": true, "dependencies": { "camel-case": "^4.1.2", "capital-case": "^1.0.4", @@ -9614,7 +9680,6 @@ "version": "10.5.0", "resolved": "https://registry.npmjs.org/chevrotain/-/chevrotain-10.5.0.tgz", "integrity": "sha512-Pkv5rBY3+CsHOYfV5g/Vs5JY9WTHHDEKOlohI2XeygaZhUeqhAlldZ8Hz9cRmxu709bvS08YzxHdTPHhffc13A==", - "dev": true, "dependencies": { "@chevrotain/cst-dts-gen": "10.5.0", "@chevrotain/gast": "10.5.0", @@ -10514,7 +10579,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", @@ -10719,8 +10783,7 @@ "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" }, "node_modules/cross-env": { "version": "7.0.3", @@ -11056,16 +11119,19 @@ } }, "node_modules/define-data-property": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", - "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-lazy-prop": { @@ -11433,7 +11499,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -11828,6 +11893,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-iterator-helpers": { "version": "1.0.15", "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", @@ -13537,15 +13621,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", - "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dependencies": { + "es-errors": "^1.3.0", "function-bind": "^1.1.2", "has-proto": "^1.0.1", "has-symbols": "^1.0.3", "hasown": "^2.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -13956,11 +14044,11 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", - "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dependencies": { - "get-intrinsic": "^1.2.2" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -14099,7 +14187,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", - "dev": true, "dependencies": { "capital-case": "^1.0.4", "tslib": "^2.0.3" @@ -14696,6 +14783,22 @@ "node": "*" } }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-array-buffer": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", @@ -14980,6 +15083,22 @@ "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", @@ -16437,6 +16556,11 @@ "node": ">=4.0" } }, + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==" + }, "node_modules/jwt-encode": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/jwt-encode/-/jwt-encode-1.0.1.tgz", @@ -16769,6 +16893,11 @@ "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==", "dev": true }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==" + }, "node_modules/lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", @@ -16988,7 +17117,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", - "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -17053,8 +17181,7 @@ "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" }, "node_modules/make-fetch-happen": { "version": "13.0.1", @@ -18609,11 +18736,46 @@ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", "dev": true }, + "node_modules/nise": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/nise/-/nise-4.1.0.tgz", + "integrity": "sha512-eQMEmGN/8arp0xsvGoQ+B1qvSkR73B1nWSCh7nOt5neMCtwcQVYQGdzQMhcNscktTsWB54xnlSQFzOAPJD8nXA==", + "dependencies": { + "@sinonjs/commons": "^1.7.0", + "@sinonjs/fake-timers": "^6.0.0", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/nise/node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/nise/node_modules/@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/nise/node_modules/path-to-regexp": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", + "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", + "dependencies": { + "isarray": "0.0.1" + } + }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", - "dev": true, "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" @@ -19743,6 +19905,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -20199,7 +20377,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", - "dev": true, "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -20257,7 +20434,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -20281,7 +20457,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", - "dev": true, "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -20290,8 +20465,7 @@ "node_modules/path-equal": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz", - "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==", - "dev": true + "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==" }, "node_modules/path-exists": { "version": "3.0.0", @@ -22279,8 +22453,7 @@ "node_modules/regexp-to-ast": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/regexp-to-ast/-/regexp-to-ast-0.5.0.tgz", - "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==", - "dev": true + "integrity": "sha512-tlbJqcMHnPKI9zSrystikWKwHkBqu2a/Sgw01h3zFjvYrMxEDYHzzoMZnUrbIfpTFEsoRnnviOXNCzFiSc54Qw==" }, "node_modules/regexp.prototype.flags": { "version": "1.5.1", @@ -22894,7 +23067,6 @@ "version": "2.4.3", "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", - "dev": true, "engines": { "node": ">=10" } @@ -23054,7 +23226,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", - "dev": true, "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", @@ -23186,14 +23357,16 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" }, "node_modules/set-function-length": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz", - "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", "dependencies": { - "define-data-property": "^1.1.1", - "get-intrinsic": "^1.2.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -23399,6 +23572,68 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/sinon": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz", + "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==", + "deprecated": "16.1.1", + "dependencies": { + "@sinonjs/commons": "^1.8.1", + "@sinonjs/fake-timers": "^6.0.1", + "@sinonjs/samsam": "^5.3.1", + "diff": "^4.0.2", + "nise": "^4.0.4", + "supports-color": "^7.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/sinon" + } + }, + "node_modules/sinon-chai": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", + "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", + "peerDependencies": { + "chai": "^4.0.0", + "sinon": ">=4.0.0" + } + }, + "node_modules/sinon/node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/sinon/node_modules/@sinonjs/fake-timers": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz", + "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -23441,7 +23676,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", - "dev": true, "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -24665,7 +24899,6 @@ "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -24708,7 +24941,6 @@ "version": "8.3.2", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", - "dev": true, "engines": { "node": ">=0.4.0" } @@ -24717,7 +24949,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, "engines": { "node": ">=0.3.1" } @@ -24996,7 +25227,6 @@ "version": "0.55.0", "resolved": "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.55.0.tgz", "integrity": "sha512-BXaivYecUdiXWWNiUqXgY6A9cMWerwmhtO+lQE7tDZGs7Mf38sORDeQZugfYOZOHPZ9ulsD+w0LWjFDOQoXcwg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", "@types/node": "^16.9.2", @@ -25014,14 +25244,12 @@ "node_modules/typescript-json-schema/node_modules/@types/node": { "version": "16.18.70", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.70.tgz", - "integrity": "sha512-8eIk20G5VVVQNZNouHjLA2b8utE2NvGybLjMaF4lyhA9uhGwnmXF8o+icdXKGSQSNANJewXva/sFUoZLwAaYAg==", - "dev": true + "integrity": "sha512-8eIk20G5VVVQNZNouHjLA2b8utE2NvGybLjMaF4lyhA9uhGwnmXF8o+icdXKGSQSNANJewXva/sFUoZLwAaYAg==" }, "node_modules/typescript-json-schema/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -25041,7 +25269,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -25053,7 +25280,6 @@ "version": "4.8.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", - "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -25277,7 +25503,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", - "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -25286,7 +25511,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", - "dev": true, "dependencies": { "tslib": "^2.0.3" } @@ -25327,6 +25551,19 @@ "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==", "dev": true }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -25363,8 +25600,7 @@ "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" }, "node_modules/v8-to-istanbul": { "version": "9.2.0", @@ -26385,7 +26621,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, "engines": { "node": ">=6" } @@ -27214,7 +27449,6 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/@commander-js/extra-typings/-/extra-typings-11.1.0.tgz", "integrity": "sha512-GuvZ38d23H+7Tz2C9DhzCepivsOsky03s5NI+KCy7ke1FNUvsJ2oO47scQ9YaGGhgjgNW5OYYNSADmbjcSoIhw==", - "dev": true, "peerDependencies": { "commander": "11.1.x" } @@ -27223,7 +27457,6 @@ "version": "11.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", - "dev": true, "engines": { "node": ">=16" } @@ -27231,7 +27464,6 @@ "packages/realm/bindgen/vendor/realm-core": { "name": "@realm/bindgen", "version": "0.1.0", - "dev": true, "dependencies": { "@commander-js/extra-typings": "^11.1.0", "@types/node": "^18.15.10", diff --git a/packages/realm/bindgen/js_opt_in_spec.yml b/packages/realm/bindgen/js_opt_in_spec.yml index b28279f781..ef80c1274e 100644 --- a/packages/realm/bindgen/js_opt_in_spec.yml +++ b/packages/realm/bindgen/js_opt_in_spec.yml @@ -569,6 +569,7 @@ classes: - start - cancel - register_download_progress_notifier + - unregister_download_progress_notifier # JS-specific - DOLLAR_resetSharedPtr diff --git a/packages/realm/package.json b/packages/realm/package.json index ed03799e88..25052101dc 100644 --- a/packages/realm/package.json +++ b/packages/realm/package.json @@ -357,4 +357,4 @@ 6 ] } -} +} \ No newline at end of file diff --git a/packages/realm/src/ProgressRealmPromise.ts b/packages/realm/src/ProgressRealmPromise.ts index 2164013b13..b041359f09 100644 --- a/packages/realm/src/ProgressRealmPromise.ts +++ b/packages/realm/src/ProgressRealmPromise.ts @@ -18,8 +18,10 @@ import { Configuration, + DynamicProgressNotificationCallback, OpenRealmBehaviorType, OpenRealmTimeOutBehavior, + PartitionBasedSyncProgressNotificationCallback, ProgressNotificationCallback, PromiseHandle, Realm, @@ -82,6 +84,8 @@ export class ProgressRealmPromise implements Promise { private handle = new PromiseHandle(); /** @internal */ private timeoutPromise: TimeoutPromise | null = null; + /** @internal */ + private token = 0; /** @internal */ constructor(config: Configuration) { @@ -134,13 +138,16 @@ export class ProgressRealmPromise implements Promise { this.handle.reject(err); } }); - // TODO: Consider storing the token returned here to unregister when the task gets cancelled, - // if for some reason, that doesn't happen internally - this.task.registerDownloadProgressNotifier(this.emitProgress); + if (this.listeners.size > 0) { + this.token = this.task.registerDownloadProgressNotifier(this.emitProgress); + } } else { throw new Error(`Unexpected open behavior '${openBehavior}'`); } } catch (err) { + if (this.token !== 0) { + this.task?.unregisterDownloadProgressNotifier(this.token); + } this.handle.reject(err); } } @@ -153,6 +160,7 @@ export class ProgressRealmPromise implements Promise { cancel(): void { this.cancelAndResetTask(); this.timeoutPromise?.cancel(); + this.task?.unregisterDownloadProgressNotifier(this.token); // Clearing all listeners to avoid accidental progress notifications this.listeners.clear(); // Tell anything awaiting the promise @@ -167,6 +175,13 @@ export class ProgressRealmPromise implements Promise { */ progress(callback: ProgressNotificationCallback): this { this.listeners.add(callback); + if (callback.length === 1) { + const estimateCallback = callback as DynamicProgressNotificationCallback; + estimateCallback(1.0); + } else { + const pbsCallback = callback as PartitionBasedSyncProgressNotificationCallback; + pbsCallback(0.0, 0.0); + } return this; } @@ -174,11 +189,17 @@ export class ProgressRealmPromise implements Promise { catch = this.handle.promise.catch.bind(this.handle.promise); finally = this.handle.promise.finally.bind(this.handle.promise); - private emitProgress = (transferredArg: binding.Int64, transferableArg: binding.Int64) => { + private emitProgress = (transferredArg: binding.Int64, transferableArg: binding.Int64, progressEstimate: number) => { const transferred = binding.Int64.intToNum(transferredArg); const transferable = binding.Int64.intToNum(transferableArg); for (const listener of this.listeners) { - listener(transferred, transferable); + if (listener.length === 1) { + const estimateListener = listener as DynamicProgressNotificationCallback; + estimateListener(progressEstimate); + } else { + const pbsListener = listener as PartitionBasedSyncProgressNotificationCallback; + pbsListener(transferred, transferable); + } } }; diff --git a/packages/realm/src/app-services/SyncSession.ts b/packages/realm/src/app-services/SyncSession.ts index ab4f908378..3b732d248f 100644 --- a/packages/realm/src/app-services/SyncSession.ts +++ b/packages/realm/src/app-services/SyncSession.ts @@ -53,13 +53,29 @@ export enum ProgressMode { ForCurrentlyOutstandingWork = "forCurrentlyOutstandingWork", } -export type ProgressNotificationCallback = +/** @deprecated */ +export type PartitionBasedSyncProgressNotificationCallback = /** + * This notification callback only supports Partition Based Sync. * @param transferred - The current number of bytes already transferred * @param transferable - The total number of transferable bytes (i.e. the number of bytes already transferred plus the number of bytes pending transfer) + * @deprecated - This notification callback will be removed in next major release. Use {@link DynamicProgressNotificationCallback} instead. + * @since 1.12.0 */ (transferred: number, transferable: number) => void; +export type DynamicProgressNotificationCallback = + /** + * This notification callback supports both Partition Based Sync and Flexible Sync. + * @param estimate - An estimate between 0.0 and 1.0 of how much have been transferred. + * @since 12.10.0 + */ + (estimate: number) => void; + +export type ProgressNotificationCallback = + | PartitionBasedSyncProgressNotificationCallback + | DynamicProgressNotificationCallback; + export enum ConnectionState { Disconnected = "disconnected", Connecting = "connecting", @@ -93,6 +109,21 @@ function toBindingDirection(direction: ProgressDirection) { } } +function isEstimateProgressNotification(cb: ProgressNotificationCallback): cb is DynamicProgressNotificationCallback { + return cb.length === 1; +} + +function toBindingProgressNotificationCallback(cb: ProgressNotificationCallback) { + if (isEstimateProgressNotification(cb)) { + return (transferredBytes: binding.Int64, transferrableBytes: binding.Int64, progressEstimate: number) => + cb(progressEstimate); + } else { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + return (transferredBytes: binding.Int64, transferrableBytes: binding.Int64, _: number) => + cb(transferrableBytes, transferrableBytes); + } +} + function fromBindingConnectionState(state: binding.SyncSessionConnectionState) { if (state === binding.SyncSessionConnectionState.Connected) { return ConnectionState.Connected; @@ -251,7 +282,7 @@ const PROGRESS_LISTENERS = new Listeners< >({ add(callback, weakInternal, internal, direction, mode) { const token = internal.registerProgressNotifier( - (transferred, transferable) => callback(Number(transferred), Number(transferable)), + toBindingProgressNotificationCallback(callback), toBindingDirection(direction), mode === ProgressMode.ReportIndefinitely, ); @@ -441,12 +472,17 @@ export class SyncSession { * Can be either: * - `reportIndefinitely` - the registration will stay active until the callback is unregistered * - `forCurrentlyOutstandingWork` - the registration will be active until only the currently transferable bytes are synced - * @param callback - Called with the following arguments: - * 1. `transferred`: The current number of bytes already transferred - * 2. `transferable`: The total number of transferable bytes (the number of bytes already transferred plus the number of bytes pending transfer) + * @param callback - see {@link DynamicProgressNotificationCallback} and {@link PartitionBasedSyncProgressNotificationCallback} + * @throws if signature of `callback` doesn't match requirements for sync mode * @since 1.12.0 */ addProgressNotification(direction: ProgressDirection, mode: ProgressMode, callback: ProgressNotificationCallback) { + if (this.config.flexible) { + assert( + isEstimateProgressNotification(callback), + `For flexible sync the callback can only take one argument - got ${callback.length} arguments`, + ); + } this.withInternal((internal) => PROGRESS_LISTENERS.add(callback, this.weakInternal, internal, direction, mode)); } /**