Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/lint-test-sdk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [ '18', '20', '22', '23' ]
node-version: [ '20', '22', '24' ]
steps:
- name: Display Testing Details
run: |
Expand Down Expand Up @@ -65,7 +65,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [ '18', '20', '22', '23' ]
node-version: [ '20', '22', '24' ]
steps:
- uses: actions/checkout@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion docs/js-client-sdk.loglevel.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ Valid log levels for the Eppo SDK logger.
**Signature:**

```typescript
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent';
export declare type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'silent';
```
49 changes: 23 additions & 26 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@eppo/js-client-sdk",
"version": "3.18.1",
"version": "4.0.0",
"description": "Eppo SDK for client-side JavaScript applications",
"main": "dist/index.js",
"files": [
Expand Down Expand Up @@ -31,43 +31,40 @@
"url": "https://github.com/Eppo-exp/js-client-sdk/issues"
},
"homepage": "https://github.com/Eppo-exp/js-client-sdk#readme",
"engines": {
"node": ">=20.0.0"
},
"devDependencies": {
"@microsoft/api-documenter": "^7.28.2",
"@microsoft/api-extractor": "^7.48.1",
"@types/jest": "^29.5.14",
"@microsoft/api-documenter": "^7.30.5",
"@microsoft/api-extractor": "^7.58.7",
"@types/jest": "^30",
"@types/spark-md5": "^3.0.5",
"@typescript-eslint/eslint-plugin": "^5.13.0",
"@typescript-eslint/parser": "^5.13.0",
"eslint": "^8.17.0",
"@typescript-eslint/eslint-plugin": "^8",
"@typescript-eslint/parser": "^8",
"eslint": "^8",
"eslint-config-prettier": "^10.1.1",
"eslint-import-resolver-typescript": "^4.3.1",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-promise": "^7.2.1",
"eslint-plugin-promise": "^7",
"husky": "^9.1.7",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"lint-staged": "^15.4.1",
"prettier": "^3.4.2",
"terser-webpack-plugin": "^5.3.3",
"jest": "^30",
"jest-environment-jsdom": "^30",
"lint-staged": "^16",
"prettier": "^3",
"terser-webpack-plugin": "^5",
"testdouble": "^3.20.2",
"ts-jest": "^29.1.1",
"ts-loader": "^9.3.1",
"ts-jest": "^29",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The pairing here is intentional and supported, not fragile.

ts-jest hasn't published a 30.x major — only the 29.x line exists. ts-jest 29.4.x explicitly declares jest 30 as a supported peer:

$ npm view ts-jest@29.4.9 peerDependencies.jest
^29.0.0 || ^30.0.0

So ts-jest ^29 IS the jest-30-compatible release. Bumping to ^30 would fail — that version doesn't exist. Reverting jest to 29 would only cost us the Node 24 support that jest 30 added, with no toolchain benefit.

The CI matrix runs lint-test-sdk + typecheck on Node 20/22/24 (all pass on this PR), and jest.config.ts is exercised by all 153 tests under that transformer.

"ts-loader": "^9",
"ts-node": "^10.9.2",
"typescript": "^5.9.3",
"webpack": "^5.73.0",
"webpack-cli": "^6.0.1"
"typescript": "^5",
"webpack": "^5",
"webpack-cli": "^6"
},
"dependencies": {
"@eppo/js-client-sdk-common": "4.15.5",
"@types/chrome": "^0.0.313",
"@eppo/js-client-sdk-common": "^5",
"@types/chrome": "^0.0.332",
"lz-string": "^1.5.0"
},
"//jest": "jest 30+ drops Node 23 support; pinned to ^29.x until we drop Node 23 from CI",
"resolutions": {
"//": "CVE-2025-7783: form-data package has a vulnerability that can be exploited to execute arbitrary code; GHSA-mh29-5h37-fv8m: js-yaml security vulnerability",
"form-data": "^4.0.4",
"js-yaml": "4.1.1"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
8 changes: 4 additions & 4 deletions src/cache/local-storage-assignment-shim.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,19 @@ export class LocalStorageAssignmentShim implements Map<string, string> {
return this.getCache().size;
}

entries(): IterableIterator<[string, string]> {
entries() {
return this.getCache().entries();
}

keys(): IterableIterator<string> {
keys() {
return this.getCache().keys();
}

values(): IterableIterator<string> {
values() {
return this.getCache().values();
}

[Symbol.iterator](): IterableIterator<[string, string]> {
[Symbol.iterator]() {
return this.getCache()[Symbol.iterator]();
}

Expand Down
12 changes: 4 additions & 8 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,15 +449,13 @@ describe('initialization options', () => {
},
} as unknown as Record<'flags', Record<string, Flag>>;

// eslint-disable-next-line @typescript-eslint/ban-types
let init: (config: IClientConfig) => Promise<EppoClient>;
// eslint-disable-next-line @typescript-eslint/ban-types
let getInstance: () => EppoClient;

beforeEach(async () => {
jest.isolateModules(() => {
// Isolate and re-require so that the static instance is reset to it's default state
// eslint-disable-next-line @typescript-eslint/no-var-requires
// eslint-disable-next-line @typescript-eslint/no-require-imports
const reloadedModule = require('./index');
init = reloadedModule.init;
getInstance = reloadedModule.getInstance;
Expand Down Expand Up @@ -1193,14 +1191,12 @@ describe('initialization options', () => {
);

describe('With reloaded index module', () => {
// eslint-disable-next-line @typescript-eslint/ban-types
let init: Function;
// eslint-disable-next-line @typescript-eslint/ban-types
let getInstance: Function;
let init: (config: IClientConfig) => Promise<EppoClient>;
let getInstance: () => EppoClient;
beforeEach(async () => {
jest.isolateModules(() => {
// Isolate and re-require so that the static instance is reset to it's default state
// eslint-disable-next-line @typescript-eslint/no-var-requires
// eslint-disable-next-line @typescript-eslint/no-require-imports
const reloadedModule = require('./index');
init = reloadedModule.init;
getInstance = reloadedModule.getInstance;
Expand Down
6 changes: 3 additions & 3 deletions src/local-storage-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export class LocalStorageEngine implements IStringStorageEngine {

try {
return LZString.decompressFromBase64(stored) || null;
} catch (e) {
} catch {
// Failed to decompress configuration, removing corrupted data
this.localStorage.removeItem(this.contentsKey);
return null;
Expand Down Expand Up @@ -117,7 +117,7 @@ export class LocalStorageEngine implements IStringStorageEngine {
migratedAt: Date.now(),
version: LocalStorageEngine.MIGRATION_VERSION,
});
} catch (e) {
} catch {
// Migration failed, continue silently
}
}
Expand All @@ -128,7 +128,7 @@ export class LocalStorageEngine implements IStringStorageEngine {
if (stored) {
return JSON.parse(stored);
}
} catch (e) {
} catch {
// Failed to parse global meta, will use default
}

Expand Down
2 changes: 1 addition & 1 deletion src/sdk-data.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
// eslint-disable-next-line @typescript-eslint/no-require-imports
const packageJson = require('../package.json');

export const sdkVersion = packageJson.version;
Expand Down
Loading
Loading