Skip to content

Commit c4cbc5f

Browse files
authored
Merge pull request #301 from powersync-ja/remove-lodash-2
Remove lodash dependency
2 parents 2bb6bce + 1c49cbf commit c4cbc5f

File tree

9 files changed

+70
-63
lines changed

9 files changed

+70
-63
lines changed

.changeset/ninety-hats-behave.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@powersync/diagnostics-app': minor
3+
'@powersync/common': minor
4+
'@powersync/web': minor
5+
---
6+
7+
Remove lodash dependency.

packages/common/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
"@rollup/plugin-json": "^6.1.0",
3737
"@rollup/plugin-node-resolve": "15.2.3",
3838
"@rollup/plugin-terser": "^0.4.4",
39-
"@types/lodash": "^4.14.197",
4039
"@types/node": "^20.5.9",
4140
"@types/uuid": "^9.0.1",
4241
"async-mutex": "^0.4.0",
@@ -45,7 +44,6 @@
4544
"can-ndjson-stream": "^1.0.2",
4645
"cross-fetch": "^4.0.0",
4746
"event-iterator": "^2.0.0",
48-
"lodash": "^4.17.21",
4947
"rollup": "4.14.3",
5048
"rsocket-core": "1.0.0-alpha.3",
5149
"rsocket-websocket-client": "1.0.0-alpha.3",

packages/common/src/client/AbstractPowerSyncDatabase.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { Mutex } from 'async-mutex';
22
import { EventIterator } from 'event-iterator';
33
import Logger, { ILogger } from 'js-logger';
4-
import throttle from 'lodash/throttle';
54
import {
65
BatchedUpdateNotification,
76
DBAdapter,
@@ -16,6 +15,7 @@ import { Schema } from '../db/schema/Schema';
1615
import { BaseObserver } from '../utils/BaseObserver';
1716
import { ControlledExecutor } from '../utils/ControlledExecutor';
1817
import { mutexRunExclusive } from '../utils/mutex';
18+
import { throttleTrailing } from '../utils/throttle.js';
1919
import { SQLOpenFactory, SQLOpenOptions, isDBAdapter, isSQLOpenFactory, isSQLOpenOptions } from './SQLOpenFactory';
2020
import { PowerSyncBackendConnector } from './connection/PowerSyncBackendConnector';
2121
import { BucketStorageAdapter, PSInternalTable } from './sync/bucket/BucketStorageAdapter';
@@ -898,14 +898,13 @@ export abstract class AbstractPowerSyncDatabase extends BaseObserver<PowerSyncDB
898898
await onChange(e);
899899
});
900900

901-
const flushTableUpdates = throttle(
901+
const flushTableUpdates = throttleTrailing(
902902
() =>
903903
this.handleTableChanges(changedTables, watchedTables, (intersection) => {
904904
if (resolvedOptions?.signal?.aborted) return;
905905
executor.schedule({ changedTables: intersection });
906906
}),
907-
throttleMs,
908-
{ leading: false, trailing: true }
907+
throttleMs
909908
);
910909

911910
const dispose = this.database.registerListener({

packages/common/src/client/sync/stream/AbstractStreamingSyncImplementation.ts

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import throttle from 'lodash/throttle';
2-
31
import Logger, { ILogger } from 'js-logger';
42

53
import { SyncStatus, SyncStatusOptions } from '../../../db/crud/SyncStatus';
@@ -18,6 +16,7 @@ import {
1816
isStreamingSyncCheckpointDiff,
1917
isStreamingSyncData
2018
} from './streaming-sync-types';
19+
import { throttleLeadingTrailing } from '../../../utils/throttle';
2120

2221
export enum LockType {
2322
CRUD = 'crud',
@@ -142,16 +141,12 @@ export abstract class AbstractStreamingSyncImplementation
142141
});
143142
this.abortController = null;
144143

145-
this.triggerCrudUpload = throttle(
146-
() => {
147-
if (!this.syncStatus.connected || this.syncStatus.dataFlowStatus.uploading) {
148-
return;
149-
}
150-
this._uploadAllCrud();
151-
},
152-
this.options.crudUploadThrottleMs,
153-
{ trailing: true }
154-
);
144+
this.triggerCrudUpload = throttleLeadingTrailing(() => {
145+
if (!this.syncStatus.connected || this.syncStatus.dataFlowStatus.uploading) {
146+
return;
147+
}
148+
this._uploadAllCrud();
149+
}, this.options.crudUploadThrottleMs!);
155150
}
156151

157152
async waitForReady() {}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/**
2+
* Throttle a function to be called at most once every "wait" milliseconds,
3+
* on the trailing edge.
4+
*
5+
* Roughly equivalent to lodash/throttle with {leading: false, trailing: true}
6+
*/
7+
export function throttleTrailing(func: () => void, wait: number) {
8+
let timeoutId: ReturnType<typeof setTimeout> | null = null;
9+
10+
const later = () => {
11+
func();
12+
timeoutId = null;
13+
};
14+
15+
return function () {
16+
if (timeoutId == null) {
17+
timeoutId = setTimeout(later, wait);
18+
}
19+
};
20+
}
21+
22+
/**
23+
* Throttle a function to be called at most once every "wait" milliseconds,
24+
* on the leading and trailing edge.
25+
*
26+
* Roughly equivalent to lodash/throttle with {leading: true, trailing: true}
27+
*/
28+
export function throttleLeadingTrailing(func: () => void, wait: number) {
29+
let timeoutId: ReturnType<typeof setTimeout> | null = null;
30+
let lastCallTime: number = 0;
31+
32+
const invokeFunction = () => {
33+
func();
34+
lastCallTime = Date.now();
35+
timeoutId = null;
36+
};
37+
38+
return function () {
39+
const now = Date.now();
40+
const timeToWait = wait - (now - lastCallTime);
41+
42+
if (timeToWait <= 0) {
43+
// Leading edge: Call the function immediately if enough time has passed
44+
invokeFunction();
45+
} else if (!timeoutId) {
46+
// Set a timeout for the trailing edge if not already set
47+
timeoutId = setTimeout(invokeFunction, timeToWait);
48+
}
49+
};
50+
}

packages/web/package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,14 @@
4242
"async-mutex": "^0.4.0",
4343
"bson": "^6.6.0",
4444
"comlink": "^4.4.1",
45-
"js-logger": "^1.6.1",
46-
"lodash": "^4.17.21"
45+
"js-logger": "^1.6.1"
4746
},
4847
"devDependencies": {
4948
"@journeyapps/wa-sqlite": "^0.3.0",
5049
"@rollup/plugin-commonjs": "^25.0.7",
5150
"@rollup/plugin-inject": "^5.0.5",
5251
"@rollup/plugin-json": "^6.1.0",
5352
"@rollup/plugin-node-resolve": "15.2.3",
54-
"@types/lodash": "^4.14.200",
5553
"@types/uuid": "^9.0.6",
5654
"@vitest/browser": "^1.3.1",
5755
"p-defer": "^4.0.1",

packages/web/tests/stream.test.ts

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,11 @@
1-
import _ from 'lodash';
1+
import { Schema, TableV2, column } from '@powersync/common';
22
import Logger from 'js-logger';
3-
import { beforeAll, describe, expect, it, vi } from 'vitest';
43
import { v4 as uuid } from 'uuid';
5-
import { AbstractPowerSyncDatabase, Schema, SyncStatusOptions, TableV2, column } from '@powersync/common';
4+
import { beforeAll, describe, expect, it, vi } from 'vitest';
65
import { MockRemote, MockStreamOpenFactory, TestConnector } from './utils/MockStreamOpenFactory';
76

87
const UPLOAD_TIMEOUT_MS = 3000;
98

10-
export async function waitForConnectionStatus(
11-
db: AbstractPowerSyncDatabase,
12-
statusCheck: SyncStatusOptions = { connected: true }
13-
) {
14-
await new Promise<void>((resolve) => {
15-
if (db.connected) {
16-
resolve();
17-
}
18-
const l = db.registerListener({
19-
statusUpdated: (status) => {
20-
if (_.every(statusCheck, (value, key) => _.isEqual(status[key as keyof SyncStatusOptions], value))) {
21-
resolve();
22-
l?.();
23-
}
24-
}
25-
});
26-
});
27-
}
28-
299
export async function generateConnectedDatabase({ useWebWorker } = { useWebWorker: true }) {
3010
/**
3111
* Very basic implementation of a listener pattern.

pnpm-lock.yaml

Lines changed: 0 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools/diagnostics-app/package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,12 @@
1515
"@mui/material": "^5.15.12",
1616
"@mui/x-data-grid": "^6.19.6",
1717
"js-logger": "^1.6.1",
18-
"lodash": "^4.17.21",
1918
"react": "^18.2.0",
2019
"react-dom": "^18.2.0",
2120
"react-router-dom": "^6.22.3"
2221
},
2322
"devDependencies": {
2423
"@swc/core": "~1.6.0",
25-
"@types/lodash": "^4.14.202",
2624
"@types/node": "^20.11.25",
2725
"@types/react": "^18.2.64",
2826
"@types/react-dom": "^18.2.21",

0 commit comments

Comments
 (0)