From bc79ad38039df1a742648db1d36f4a6a1ba679e9 Mon Sep 17 00:00:00 2001 From: Casey Waldren <cwaldren@launchdarkly.com> Date: Thu, 12 Dec 2024 11:13:33 -0800 Subject: [PATCH] feat: add releases product to api-js --- api-js/src/SDKMeta.ts | 33 ++++++++++++++++++++++++++ api-js/tests/e2e.test.ts | 51 +++++++++++++++++++++++++++++++++++++--- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/api-js/src/SDKMeta.ts b/api-js/src/SDKMeta.ts index 169c4fa..a97d2e7 100644 --- a/api-js/src/SDKMeta.ts +++ b/api-js/src/SDKMeta.ts @@ -3,6 +3,7 @@ import sdkRepos from './data/repos.json' import sdkNames from './data/names.json' import sdkTypes from './data/types.json' import sdkPopularity from './data/popularity.json' +import sdkReleases from './data/releases.json' export enum Type { // ClientSide is an SDK that runs in a client scenario. @@ -29,9 +30,41 @@ export const Languages: Record<string, string[]> = sdkLanguages; export const Names: Record<string, string> = sdkNames; export const Repos: Record<string, Repo> = sdkRepos; export const Popularity: Record<string, number> = sdkPopularity; +export const Releases: ReleaseList = Object.fromEntries( + Object.entries(sdkReleases).map(([key, value]) => [ + key, + value.map((release: any) => ({ + Major: release["major"], + Minor: release["minor"], + Date: new Date(release["date"]), + EOL: release["eol"] ? new Date(release["eol"]) : null + })) + ])); export const Types: Record<string, Type> = Object.fromEntries( Object.entries(sdkTypes).map(([key, value]) => [ key, isType(value) ? value : Type.Unknown ])); + + +export interface Release { + Major: number; + Minor: number; + Date: Date; + EOL: Date | null; +} + +export interface ReleaseList { + [key: string]: Release[]; +} + +export namespace ReleaseHelpers { + export const IsLatest = (release: Release) => release.EOL === null; + export const IsEOL = (release: Release, now: Date) => !IsLatest(release) && now > release.EOL!; + export const IsApproachingEOL = (release: Release, now: Date, thresholdPrior: number) => + !IsLatest(release) && now.getTime() + thresholdPrior > release.EOL!.getTime(); + + export const Earliest = (releases: Release[]) => releases[releases.length - 1]; + export const Latest = (releases: Release[]) => releases[0]; +} diff --git a/api-js/tests/e2e.test.ts b/api-js/tests/e2e.test.ts index bd231af..98ee044 100644 --- a/api-js/tests/e2e.test.ts +++ b/api-js/tests/e2e.test.ts @@ -1,4 +1,4 @@ -import { Names, Repos, Types, Type, Popularity, Languages } from '../src/SDKMeta'; +import { Names, Repos, Types, Type, Popularity, Languages, Releases, ReleaseHelpers } from '../src/SDKMeta'; test('names', () => { expect(Names['node-server']).toBe('Node.js Server SDK'); @@ -17,8 +17,53 @@ test('types', () => { expect(Types['node-server']).toBe('server-side'); }); - - test('popularity', () => { expect(Popularity['node-server']).toBe(2); }); + +test('releases', () => { + const firstNodeReleaseDate = new Date("2015-05-13T16:55:00Z"); + const firstNodeReleaseEOL = new Date("2016-09-12T00:00:00Z"); + + expect(Releases['node-server'].length).toBeGreaterThanOrEqual(1); + + const firstRelease = ReleaseHelpers.Earliest(Releases['node-server']); + expect(firstRelease.Major).toBe(1); + expect(firstRelease.Minor).toBe(0); + expect(ReleaseHelpers.IsLatest(firstRelease)).toBe(false); + + expect(firstRelease.Date).toEqual(firstNodeReleaseDate); + expect(firstRelease.EOL).not.toBeNull(); + expect(firstRelease.EOL).toEqual(firstNodeReleaseEOL); + + const latestRelease = ReleaseHelpers.Latest(Releases['node-server']); + expect(latestRelease.Major).toBeGreaterThanOrEqual(9); + expect(latestRelease.Minor).toBeGreaterThanOrEqual(4); + expect(latestRelease.EOL).toBeNull(); + expect(ReleaseHelpers.IsLatest(latestRelease)).toBe(true); +}) + +test('eol calculations', () => { + const releases = Releases['node-server']; + const earliest = ReleaseHelpers.Earliest(releases); + const latest = ReleaseHelpers.Latest(releases); + const earliestEOL = new Date("2016-09-12T00:00:00Z"); + + // Checking that the latest release is not yet EOL + expect(ReleaseHelpers.IsEOL(latest, new Date())).toBe(false); + // Checking that the earliest release becomes EOL if we pass in a "current" date of its EOL + 1 second + expect(ReleaseHelpers.IsEOL(earliest, new Date(earliestEOL.getTime() + 1000))).toBe(true); + + // Check the "approaching EOL" logic for the earliest release by passing in different values of "current" date. + const minute = 60 * 1000; + const hour = 60 * minute; + const hour_and_1_minute = 61 * minute; + const fifty_nine_minutes = 59 * minute; + const thirty_minutes = 30 * minute; + + expect(ReleaseHelpers.IsApproachingEOL(earliest, new Date(earliestEOL.getTime() - hour_and_1_minute), hour)).toBe(false); + expect(ReleaseHelpers.IsApproachingEOL(earliest, new Date(earliestEOL.getTime() - hour), hour)).toBe(false); + expect(ReleaseHelpers.IsApproachingEOL(earliest, new Date(earliestEOL.getTime() - fifty_nine_minutes), hour)).toBe(true); + expect(ReleaseHelpers.IsApproachingEOL(earliest, new Date(earliestEOL.getTime() - thirty_minutes), hour)).toBe(true); + expect(ReleaseHelpers.IsApproachingEOL(earliest, new Date(earliestEOL.getTime() - minute), hour)).toBe(true); +})