Skip to content

Commit ba443c2

Browse files
authored
chore: tsc strict, CI test matrix (#101)
* chore: tsc strict, CI test matrix * minor cleanup * braces
1 parent 53cc624 commit ba443c2

File tree

6 files changed

+133
-109
lines changed

6 files changed

+133
-109
lines changed

.github/workflows/lint-test-sdk.yml

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,28 +21,34 @@ on:
2121
env:
2222
SDK_BRANCH_NAME: ${{ inputs.sdk_branch || github.head_ref || github.ref_name || 'main' }}
2323
TEST_DATA_BRANCH_NAME: ${{ inputs.test_data_branch || 'main' }}
24-
24+
2525
jobs:
2626
lint-test-sdk:
2727
runs-on: ubuntu-latest
28+
strategy:
29+
matrix:
30+
node-version: [ '18', '20', '22', '23' ]
2831
steps:
2932
- name: Display Testing Details
3033
run: |
3134
echo "Running SDK Test using"
3235
echo "Test Data: sdk-test-data@${TEST_DATA_BRANCH_NAME}"
3336
echo "SDK Branch: js-client-sdk@${SDK_BRANCH_NAME}"
34-
- uses: actions/checkout@v2
35-
with:
36-
repository: Eppo-exp/js-client-sdk
37-
ref: ${{ env.SDK_BRANCH_NAME }}
37+
- uses: actions/checkout@v3
3838
- name: Use Node.js
39-
uses: actions/setup-node@v1
39+
uses: actions/setup-node@v3
4040
with:
41-
node-version: '18.x'
42-
- uses: actions/cache@v2
41+
node-version: ${{ matrix.node-version }}
42+
- name: Get yarn cache directory path
43+
id: yarn-cache-dir-path
44+
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
45+
- uses: actions/cache@v4
46+
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
4347
with:
44-
path: './node_modules'
45-
key: ${{ runner.os }}-root-node-modules-${{ hashFiles('./yarn.lock') }}
48+
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
49+
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
50+
restore-keys: |
51+
${{ runner.os }}-yarn-
4652
- name: Install SDK dependencies
4753
run: yarn --frozen-lockfile
4854
working-directory: ./
@@ -54,19 +60,25 @@ jobs:
5460
working-directory: ./
5561
typecheck:
5662
runs-on: ubuntu-latest
63+
strategy:
64+
matrix:
65+
node-version: [ '18', '20', '22', '23' ]
5766
steps:
58-
- uses: actions/checkout@v2
59-
with:
60-
repository: Eppo-exp/js-client-sdk
61-
ref: ${{ env.SDK_BRANCH_NAME }}
67+
- uses: actions/checkout@v3
6268
- name: Use Node.js
63-
uses: actions/setup-node@v1
69+
uses: actions/setup-node@v3
6470
with:
65-
node-version: '18.x'
66-
- uses: actions/cache@v2
71+
node-version: ${{ matrix.node-version }}
72+
- name: Get yarn cache directory path
73+
id: yarn-cache-dir-path
74+
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
75+
- uses: actions/cache@v4
76+
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
6777
with:
68-
path: './node_modules'
69-
key: ${{ runner.os }}-root-node-modules-${{ hashFiles('./yarn.lock') }}
78+
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
79+
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
80+
restore-keys: |
81+
${{ runner.os }}-yarn-
7082
- name: Install SDK dependencies
7183
run: yarn --frozen-lockfile
7284
working-directory: ./

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,6 @@
6060
},
6161
"dependencies": {
6262
"@eppo/js-client-sdk-common": "4.3.0"
63-
}
64-
}
63+
},
64+
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
65+
}
Lines changed: 1 addition & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import { AbstractAssignmentCache } from '@eppo/js-client-sdk-common';
22

3-
import { hasWindowLocalStorage } from '../configuration-factory';
4-
53
import { BulkReadAssignmentCache, BulkWriteAssignmentCache } from './hybrid-assignment-cache';
4+
import { LocalStorageAssignmentShim } from './local-storage-assignment-shim';
65

76
export class LocalStorageAssignmentCache
87
extends AbstractAssignmentCache<LocalStorageAssignmentShim>
@@ -24,74 +23,3 @@ export class LocalStorageAssignmentCache
2423
return Promise.resolve(Array.from(this.entries()));
2524
}
2625
}
27-
28-
// noinspection JSUnusedGlobalSymbols (methods are used by common repository)
29-
class LocalStorageAssignmentShim implements Map<string, string> {
30-
private readonly localStorageKey: string;
31-
32-
public constructor(storageKeySuffix: string) {
33-
if (!hasWindowLocalStorage()) {
34-
throw new Error('LocalStorage is not available');
35-
}
36-
const keySuffix = storageKeySuffix ? `-${storageKeySuffix}` : '';
37-
this.localStorageKey = `eppo-assignment${keySuffix}`;
38-
}
39-
40-
clear(): void {
41-
this.getCache().clear();
42-
}
43-
44-
delete(key: string): boolean {
45-
return this.getCache().delete(key);
46-
}
47-
48-
forEach(
49-
callbackfn: (value: string, key: string, map: Map<string, string>) => void,
50-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
51-
thisArg?: any,
52-
): void {
53-
this.getCache().forEach(callbackfn, thisArg);
54-
}
55-
56-
size: number;
57-
58-
entries(): IterableIterator<[string, string]> {
59-
return this.getCache().entries();
60-
}
61-
62-
keys(): IterableIterator<string> {
63-
return this.getCache().keys();
64-
}
65-
66-
values(): IterableIterator<string> {
67-
return this.getCache().values();
68-
}
69-
70-
[Symbol.iterator](): IterableIterator<[string, string]> {
71-
return this.getCache()[Symbol.iterator]();
72-
}
73-
74-
[Symbol.toStringTag]: string;
75-
76-
public has(key: string): boolean {
77-
return this.getCache().has(key);
78-
}
79-
80-
public get(key: string): string | undefined {
81-
return this.getCache().get(key) ?? undefined;
82-
}
83-
84-
public set(key: string, value: string): this {
85-
return this.setCache(this.getCache().set(key, value));
86-
}
87-
88-
private getCache(): Map<string, string> {
89-
const cache = window.localStorage.getItem(this.localStorageKey);
90-
return cache ? new Map(JSON.parse(cache)) : new Map();
91-
}
92-
93-
private setCache(cache: Map<string, string>): this {
94-
window.localStorage.setItem(this.localStorageKey, JSON.stringify(Array.from(cache.entries())));
95-
return this;
96-
}
97-
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// noinspection JSUnusedGlobalSymbols (methods are used by common repository)
2+
import { hasWindowLocalStorage } from '../configuration-factory';
3+
4+
export class LocalStorageAssignmentShim implements Map<string, string> {
5+
private readonly localStorageKey: string;
6+
7+
public constructor(storageKeySuffix: string) {
8+
if (!hasWindowLocalStorage()) {
9+
throw new Error('LocalStorage is not available');
10+
}
11+
const keySuffix = storageKeySuffix ? `-${storageKeySuffix}` : '';
12+
this.localStorageKey = `eppo-assignment${keySuffix}`;
13+
}
14+
15+
clear(): void {
16+
this.getCache().clear();
17+
}
18+
19+
delete(key: string): boolean {
20+
return this.getCache().delete(key);
21+
}
22+
23+
forEach(
24+
callbackfn: (value: string, key: string, map: Map<string, string>) => void,
25+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
26+
thisArg?: any,
27+
): void {
28+
this.getCache().forEach(callbackfn, thisArg);
29+
}
30+
31+
size: number = this.getCache().size;
32+
33+
entries(): IterableIterator<[string, string]> {
34+
return this.getCache().entries();
35+
}
36+
37+
keys(): IterableIterator<string> {
38+
return this.getCache().keys();
39+
}
40+
41+
values(): IterableIterator<string> {
42+
return this.getCache().values();
43+
}
44+
45+
[Symbol.iterator](): IterableIterator<[string, string]> {
46+
return this.getCache()[Symbol.iterator]();
47+
}
48+
49+
[Symbol.toStringTag]: string = this.getCache()[Symbol.toStringTag];
50+
51+
public has(key: string): boolean {
52+
return this.getCache().has(key);
53+
}
54+
55+
public get(key: string): string | undefined {
56+
return this.getCache().get(key) ?? undefined;
57+
}
58+
59+
public set(key: string, value: string): this {
60+
return this.setCache(this.getCache().set(key, value));
61+
}
62+
63+
private getCache(): Map<string, string> {
64+
const cache = window.localStorage.getItem(this.localStorageKey);
65+
return cache ? new Map(JSON.parse(cache)) : new Map();
66+
}
67+
68+
private setCache(cache: Map<string, string>): this {
69+
window.localStorage.setItem(this.localStorageKey, JSON.stringify(Array.from(cache.entries())));
70+
return this;
71+
}
72+
}

src/index.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,21 @@ export async function init(config: IClientConfig): Promise<EppoClient> {
401401
validation.validateNotBlank(config.apiKey, 'API key required');
402402
let initializationError: Error | undefined;
403403
const instance = EppoJSClient.instance;
404-
const { apiKey, persistentStore, baseUrl, maxCacheAgeSeconds, updateOnFetch, forceReinitialize } =
405-
config;
404+
const {
405+
apiKey,
406+
persistentStore,
407+
baseUrl,
408+
maxCacheAgeSeconds,
409+
updateOnFetch,
410+
forceReinitialize,
411+
requestTimeoutMs,
412+
numInitialRequestRetries,
413+
numPollRequestRetries,
414+
pollingIntervalMs,
415+
pollAfterSuccessfulInitialization = false,
416+
pollAfterFailedInitialization = false,
417+
skipInitialRequest = false,
418+
} = config;
406419
try {
407420
if (EppoJSClient.initialized) {
408421
if (forceReinitialize) {
@@ -461,14 +474,14 @@ export async function init(config: IClientConfig): Promise<EppoClient> {
461474
sdkName,
462475
sdkVersion,
463476
baseUrl,
464-
requestTimeoutMs: config.requestTimeoutMs ?? undefined,
465-
numInitialRequestRetries: config.numInitialRequestRetries ?? undefined,
466-
numPollRequestRetries: config.numPollRequestRetries ?? undefined,
467-
pollAfterSuccessfulInitialization: config.pollAfterSuccessfulInitialization ?? false,
468-
pollAfterFailedInitialization: config.pollAfterFailedInitialization ?? false,
469-
pollingIntervalMs: config.pollingIntervalMs ?? undefined,
477+
requestTimeoutMs,
478+
numInitialRequestRetries,
479+
numPollRequestRetries,
480+
pollAfterSuccessfulInitialization,
481+
pollAfterFailedInitialization,
482+
pollingIntervalMs,
470483
throwOnFailedInitialization: true, // always use true here as underlying instance fetch is surrounded by try/catch
471-
skipInitialPoll: config.skipInitialRequest ?? false,
484+
skipInitialPoll: skipInitialRequest,
472485
};
473486
instance.setConfigurationRequestParameters(requestConfiguration);
474487

@@ -504,9 +517,7 @@ export async function init(config: IClientConfig): Promise<EppoClient> {
504517
});
505518
const attemptInitFromFetch = instance
506519
.fetchFlagConfigurations()
507-
.then(() => {
508-
return 'fetch';
509-
})
520+
.then(() => 'fetch')
510521
.catch((e) => {
511522
applicationLogger.warn('Eppo SDK encountered an error initializing from fetching', e);
512523
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -531,7 +542,7 @@ export async function init(config: IClientConfig): Promise<EppoClient> {
531542
// both failed, make the "fatal" error the fetch one
532543
initializationError = initFromFetchError;
533544
}
534-
} catch (error) {
545+
} catch (error: any) {
535546
initializationError = error;
536547
}
537548

tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"target": "es2017",
99
"outDir": "dist",
1010
"noImplicitAny": true,
11-
"strictNullChecks": true
11+
"strict": true
1212
},
1313
"include": [
1414
"src/**/*.ts"
@@ -19,4 +19,4 @@
1919
"src/**/*.spec.ts",
2020
"test/**/*"
2121
]
22-
}
22+
}

0 commit comments

Comments
 (0)