Skip to content

Commit

Permalink
refactor: detect api version using known responses
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel J. Lauk committed Nov 16, 2021
1 parent d9cd35a commit 3ac978c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 16 deletions.
38 changes: 34 additions & 4 deletions src/api/util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,45 @@ describe('module api/util', () => {
})

describe('detectVersion', () => {
it('returns version string from version field in response', async () => {
const version = '1.2.3-rc4'
it('returns version string for API v4 with major and minor', async () => {
const expectedVersion = '4.2'
mockedFetch.mockResolvedValueOnce({
ok: true,
status: 200,
json: () => Promise.resolve({ version }),
json: () =>
Promise.resolve({ data_api_version: { major: 4, minor: 2 } }),
} as Response)
const actualVersion = await detectVersion(DEFAULT_URL)
expect(actualVersion).toBe(version)
expect(actualVersion).toBe(expectedVersion)
})

it('returns version string for API v4 with major version only', async () => {
const expectedVersion = '4'
mockedFetch.mockResolvedValueOnce({
ok: true,
status: 200,
json: () => Promise.resolve({ data_api_version: { major: 4 } }),
} as Response)
const actualVersion = await detectVersion(DEFAULT_URL)
expect(actualVersion).toBe(expectedVersion)
})

it('throws if unsupported response format', async () => {
mockedFetch.mockResolvedValueOnce({
ok: true,
status: 200,
json: () =>
Promise.resolve({
new_version_structure: {
major: 5,
minor: 2,
patch: 7,
text: '5.2.7',
build: 'experimental',
},
}),
} as Response)
await expect(detectVersion(DEFAULT_URL)).rejects.toThrow()
})

it('returns undefined on HTTP 404', async () => {
Expand Down
25 changes: 13 additions & 12 deletions src/api/util.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import * as decoders from 'decoders'
import { fetchWithTimeout } from '../http'

type VersionInfo = {
version: string
}
const versionGuard = decoders.guard(
decoders.object({ version: decoders.string })
)
import { dataApiVersionResponseGuard } from './v4/apiv4decoders'

/**
* Contact the API provider at base URL `url` and try to read
Expand All @@ -24,17 +17,25 @@ export const detectVersion = async (
headers: { Accept: 'application/json' },
})
if (resp.status === 404) {
return undefined
return undefined // OK, this API provider doesn't provide a /version endpoint
}
if (!resp.ok) {
throw new Error(
`could not detect version: ${resp.status} ${resp.statusText}`
)
}
const respData: unknown = await resp.json()
// in turn, try each known API version
try {
const versionInfo: VersionInfo = versionGuard(await resp.json())
return versionInfo.version
const tmp = dataApiVersionResponseGuard(respData)
let v = `${tmp.data_api_version.major}`
if (tmp.data_api_version.minor) {
v += `.${tmp.data_api_version.minor}`
}
return v
} catch (e) {
throw new Error('received malformed version info')
// decoder throws error --> it's not Data API V4; try next one (if there is any)
}
// out of known API versions / providers --> throw error
throw new Error('could not identify version from API response')
}

0 comments on commit 3ac978c

Please sign in to comment.