diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index da4132be3..62d691b7b 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -57,7 +57,7 @@ jobs: run: BUILD_BRANCH=$(echo "${GITHUB_REF#refs/heads/}") npm run build - name: Store assets - if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/development' || github.ref == 'refs/heads/main') }} + if: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/fme-12310' || github.ref == 'refs/heads/main') }} uses: actions/upload-artifact@v5 with: name: assets @@ -68,7 +68,7 @@ jobs: name: Upload assets runs-on: ubuntu-latest needs: build - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/development' }} + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/fme-12310' }} strategy: matrix: environment: diff --git a/package-lock.json b/package-lock.json index a185a39bb..40a2f0122 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@splitsoftware/splitio", - "version": "11.9.1", + "version": "11.9.2-rc.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio", - "version": "11.9.1", + "version": "11.9.2-rc.4", "license": "Apache-2.0", "dependencies": { - "@splitsoftware/splitio-commons": "2.10.1", + "@splitsoftware/splitio-commons": "2.10.2-rc.7", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", @@ -352,9 +352,9 @@ "dev": true }, "node_modules/@splitsoftware/splitio-commons": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.10.1.tgz", - "integrity": "sha512-yYmWC1stuH2DvxEXP9xZFOOvw3SkRDjE5UwZ68y011Oev9ILXSN7E2Yd6w8ag85cwbF5GjtaDgT7bOURhyvKww==", + "version": "2.10.2-rc.7", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.10.2-rc.7.tgz", + "integrity": "sha512-WGQDs2v2dIdCnvT8SDjWej2mPYK05Zgzbjbv4LK/GNa8I+UpEjYOzkTCY89TVn2Uy8uQr8B1SRej4VBK0Lvnmw==", "license": "Apache-2.0", "dependencies": { "@types/ioredis": "^4.28.0", @@ -6837,10 +6837,11 @@ } }, "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -7831,9 +7832,9 @@ "dev": true }, "@splitsoftware/splitio-commons": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.10.1.tgz", - "integrity": "sha512-yYmWC1stuH2DvxEXP9xZFOOvw3SkRDjE5UwZ68y011Oev9ILXSN7E2Yd6w8ag85cwbF5GjtaDgT7bOURhyvKww==", + "version": "2.10.2-rc.7", + "resolved": "https://registry.npmjs.org/@splitsoftware/splitio-commons/-/splitio-commons-2.10.2-rc.7.tgz", + "integrity": "sha512-WGQDs2v2dIdCnvT8SDjWej2mPYK05Zgzbjbv4LK/GNa8I+UpEjYOzkTCY89TVn2Uy8uQr8B1SRej4VBK0Lvnmw==", "requires": { "@types/ioredis": "^4.28.0", "tslib": "^2.3.1" @@ -12818,9 +12819,9 @@ } }, "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "requires": { "@cspotcode/source-map-support": "^0.8.0", diff --git a/package.json b/package.json index e5dec9956..569e88629 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio", - "version": "11.9.1", + "version": "11.9.2-rc.4", "description": "Split SDK", "files": [ "README.md", @@ -38,7 +38,7 @@ "node": ">=14.0.0" }, "dependencies": { - "@splitsoftware/splitio-commons": "2.10.1", + "@splitsoftware/splitio-commons": "2.10.2-rc.7", "bloom-filters": "^3.0.4", "ioredis": "^4.28.0", "js-yaml": "^3.13.1", diff --git a/src/__tests__/browserSuites/push-corner-cases.spec.js b/src/__tests__/browserSuites/push-corner-cases.spec.js index 37edd1587..d953d8129 100644 --- a/src/__tests__/browserSuites/push-corner-cases.spec.js +++ b/src/__tests__/browserSuites/push-corner-cases.spec.js @@ -97,7 +97,7 @@ export function testSplitKillOnReadyFromCache(fetchMock, assert) { }); client.on(client.Event.SDK_READY, () => { const lapse = Date.now() - start; - assert.true(nearlyEqual(lapse, MILLIS_SPLIT_CHANGES_RESPONSE), 'SDK_READY once split changes arrives'); + assert.true(nearlyEqual(lapse, MILLIS_SPLIT_CHANGES_RESPONSE, 200), 'SDK_READY once split changes arrives'); client.destroy().then(() => { assert.end(); }); }); diff --git a/src/__tests__/browserSuites/ready-from-cache.spec.js b/src/__tests__/browserSuites/ready-from-cache.spec.js index bacbf2cbb..fbcabb20a 100644 --- a/src/__tests__/browserSuites/ready-from-cache.spec.js +++ b/src/__tests__/browserSuites/ready-from-cache.spec.js @@ -371,8 +371,8 @@ export default function (fetchMock, assert) { t.true(Date.now() - startTime >= 400, 'It should emit SDK_READY too but after syncing with the cloud.'); t.equal(client.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); - client.whenReadyFromCache().then((isReady) => { - t.false(isReady, 'It should be ready from cache before ready (syncing with the cloud).'); + client.whenReadyFromCache().then((metadata) => { + t.false(metadata.initialCacheLoad, 'It should be ready from cache before ready (syncing with the cloud).'); t.true(Date.now() - startTime < 50, 'It should resolve ready from cache promise almost immediately.'); }); client.whenReady().then(() => { @@ -383,8 +383,8 @@ export default function (fetchMock, assert) { t.true(Date.now() - startTime >= 700, 'It should emit SDK_READY too but after syncing with the cloud.'); t.equal(client2.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); - client2.whenReadyFromCache().then((isReady) => { - t.false(isReady, 'It should be ready from cache before ready (syncing with the cloud).'); + client2.whenReadyFromCache().then((metadata) => { + t.false(metadata.initialCacheLoad, 'It should be ready from cache before ready (syncing with the cloud).'); }); client2.whenReady().then(() => { t.true(Date.now() - startTime >= 700, 'It should resolve ready promise after syncing with the cloud.'); @@ -488,8 +488,8 @@ export default function (fetchMock, assert) { t.true(nearlyEqual(Date.now() - startTime, CLIENT_READY_MS), 'It should emit SDK_READY after syncing with the cloud.'); t.equal(client.getTreatment('always_on'), 'on', 'It should evaluate treatments with updated data after syncing with the cloud.'); }); - client.whenReadyFromCache().then((isReady) => { - t.true(isReady, 'It should be ready from cache and ready.'); + client.whenReadyFromCache().then((metadata) => { + t.true(metadata.initialCacheLoad, 'It should be ready from cache and ready.'); t.true(nearlyEqual(Date.now() - startTime, CLIENT_READY_MS), 'It should resolve ready from cache promise after syncing with the cloud.'); }); client.whenReady().then(() => { diff --git a/src/__tests__/browserSuites/ready-promise.spec.js b/src/__tests__/browserSuites/ready-promise.spec.js index f632a177c..abd2dcd0d 100644 --- a/src/__tests__/browserSuites/ready-promise.spec.js +++ b/src/__tests__/browserSuites/ready-promise.spec.js @@ -521,7 +521,7 @@ export default function readyPromiseAssertions(fetchMock, assert) { consoleSpy.log.resetHistory(); setTimeout(() => { - client.whenReadyFromCache().then((isReady) => t.true(isReady, 'SDK IS READY (& READY FROM CACHE) - Should resolve')).catch(() => t.fail('SDK TIMED OUT - Should not reject')); + client.whenReadyFromCache().then((metadata) => t.true(metadata.initialCacheLoad, 'SDK IS READY (& READY FROM CACHE) - Should resolve')).catch(() => t.fail('SDK TIMED OUT - Should not reject')); assertGetTreatmentWhenReady(t, client); diff --git a/src/__tests__/nodeSuites/ready-promise.spec.js b/src/__tests__/nodeSuites/ready-promise.spec.js index c62c060fe..bdcfd2737 100644 --- a/src/__tests__/nodeSuites/ready-promise.spec.js +++ b/src/__tests__/nodeSuites/ready-promise.spec.js @@ -494,7 +494,7 @@ export default function readyPromiseAssertions(key, fetchMock, assert) { consoleSpy.log.resetHistory(); setTimeout(() => { - client.whenReadyFromCache().then((isReady) => t.true(isReady, 'SDK IS READY (& READY FROM CACHE) - Should resolve')).catch(() => t.fail('SDK TIMED OUT - Should not reject')); + client.whenReadyFromCache().then((metadata) => t.true(metadata.initialCacheLoad, 'SDK IS READY (& READY FROM CACHE) - Should resolve')).catch(() => t.fail('SDK TIMED OUT - Should not reject')); assertGetTreatmentWhenReady(t, client, key); diff --git a/src/settings/defaults/version.js b/src/settings/defaults/version.js index cbc6b4aa3..983e1e78a 100644 --- a/src/settings/defaults/version.js +++ b/src/settings/defaults/version.js @@ -1 +1 @@ -export const packageVersion = '11.9.1'; +export const packageVersion = '11.9.2-rc.4'; diff --git a/ts-tests/index.ts b/ts-tests/index.ts index e807fc913..fa2f02e0c 100644 --- a/ts-tests/index.ts +++ b/ts-tests/index.ts @@ -258,12 +258,12 @@ let nodeEventEmitter: NodeJS.EventEmitter = client; // Ready, destroy and flush let promise: Promise = client.ready(); -promise = client.whenReady(); promise = client.destroy(); promise = SDK.destroy(); // @TODO not public yet // promise = client.flush(); -let promiseWhenReadyFromCache: Promise = client.whenReadyFromCache(); +let promiseWithMetadata: Promise = client.whenReady(); +promiseWithMetadata = client.whenReadyFromCache(); // Get readiness status let status: SplitIO.ReadinessStatus = client.getStatus(); @@ -358,6 +358,62 @@ tracked = browserClient.track('myTrafficType', 'myEventType', 10); // Properties parameter is optional on all signatures. tracked = client.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: false, prop4: null }); tracked = browserClient.track('myTrafficType', 'myEventType', undefined, { prop1: 1, prop2: '2', prop3: false, prop4: null }); +/*** Tests for SDK Update Metadata ***/ + +// Using addListener with typed metadata +client.addListener(client.Event.SDK_UPDATE, (metadata: SplitIO.SdkUpdateMetadata) => { + const type: SplitIO.SdkUpdateMetadataType = metadata.type; + const names: string[] = metadata.names; +}); +client.addListener(client.Event.SDK_READY, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); +client.addListener(client.Event.SDK_READY_FROM_CACHE, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); +client.addListener(client.Event.SDK_UPDATE, () => { }); +client.addListener(client.Event.SDK_READY, () => { }); +client.addListener(client.Event.SDK_READY_FROM_CACHE, () => { }); + +// Using once with typed metadata +client.once(client.Event.SDK_UPDATE, (metadata: SplitIO.SdkUpdateMetadata) => { + const type: SplitIO.SdkUpdateMetadataType = metadata.type; + const names: string[] = metadata.names; +}); +client.once(client.Event.SDK_READY, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); +client.once(client.Event.SDK_READY_FROM_CACHE, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); +client.once(client.Event.SDK_UPDATE, () => { }); +client.once(client.Event.SDK_READY, () => { }); +client.once(client.Event.SDK_READY_FROM_CACHE, () => { }); + +// SDK_READY event listener with metadata +client.on(client.Event.SDK_READY, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); + +// SDK_READY_FROM_CACHE event listener with metadata +client.on(client.Event.SDK_READY_FROM_CACHE, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); + +// SDK_UPDATE event listener with metadata +client.on(client.Event.SDK_UPDATE, (metadata: SplitIO.SdkUpdateMetadata) => { + const type: SplitIO.SdkUpdateMetadataType = metadata.type; + const names: string[] = metadata.names; +}); +client.on(client.Event.SDK_UPDATE, () => { }); +client.on(client.Event.SDK_READY, () => { }); +client.on(client.Event.SDK_READY_FROM_CACHE, () => { }); /*** Repeating tests for Async Client ***/ @@ -378,12 +434,12 @@ nodeEventEmitter = asyncClient; // Ready, destroy and flush (same as for sync client, just for interface checking) promise = asyncClient.ready(); -promise = asyncClient.whenReady(); promise = asyncClient.destroy(); promise = AsyncSDK.destroy(); // @TODO not public yet // promise = asyncClient.flush(); -promiseWhenReadyFromCache = asyncClient.whenReadyFromCache(); +promiseWithMetadata = asyncClient.whenReady(); +promiseWithMetadata = asyncClient.whenReadyFromCache(); // Get readiness status status = asyncClient.getStatus(); @@ -443,6 +499,63 @@ trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10); // Properties parameter is optional trackPromise = asyncClient.track(splitKey, 'myTrafficType', 'myEventType', 10, { prop1: 1, prop2: '2', prop3: true, prop4: null }); +/*** Tests for SDK Update Metadata ***/ + +// Using addListener with typed metadata +asyncClient.addListener(asyncClient.Event.SDK_UPDATE, (metadata: SplitIO.SdkUpdateMetadata) => { + const type: SplitIO.SdkUpdateMetadataType = metadata.type; + const names: string[] = metadata.names; +}); +asyncClient.addListener(asyncClient.Event.SDK_READY, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); +asyncClient.addListener(asyncClient.Event.SDK_READY_FROM_CACHE, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); +asyncClient.addListener(asyncClient.Event.SDK_UPDATE, () => { }); +asyncClient.addListener(asyncClient.Event.SDK_READY, () => { }); +asyncClient.addListener(asyncClient.Event.SDK_READY_FROM_CACHE, () => { }); + +// Using once with typed metadata +asyncClient.once(asyncClient.Event.SDK_UPDATE, (metadata: SplitIO.SdkUpdateMetadata) => { + const type: SplitIO.SdkUpdateMetadataType = metadata.type; + const names: string[] = metadata.names; +}); +asyncClient.once(asyncClient.Event.SDK_READY, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); +asyncClient.once(asyncClient.Event.SDK_READY_FROM_CACHE, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); +asyncClient.once(asyncClient.Event.SDK_UPDATE, () => { }); +asyncClient.once(asyncClient.Event.SDK_READY, () => { }); +asyncClient.once(asyncClient.Event.SDK_READY_FROM_CACHE, () => { }); + +// SDK_READY event listener with metadata +asyncClient.on(asyncClient.Event.SDK_READY, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); + +// SDK_READY_FROM_CACHE event listener with metadata +asyncClient.on(asyncClient.Event.SDK_READY_FROM_CACHE, (metadata: SplitIO.SdkReadyMetadata) => { + const fromCache: boolean = metadata.initialCacheLoad; + const timestamp: number = metadata.lastUpdateTimestamp; +}); + +// SDK_UPDATE event listener with metadata +asyncClient.on(asyncClient.Event.SDK_UPDATE, (metadata: SplitIO.SdkUpdateMetadata) => { + const type: SplitIO.SdkUpdateMetadataType = metadata.type; + const names: string[] = metadata.names; +}); +asyncClient.on(asyncClient.Event.SDK_UPDATE, () => { }); +asyncClient.on(asyncClient.Event.SDK_READY, () => { }); +asyncClient.on(asyncClient.Event.SDK_READY_FROM_CACHE, () => { }); + /**** Tests for IManager interface ****/ splitNames = manager.names();