evenietminus
Version:
An abstract layer over openWeatherMap APIs
260 lines (217 loc) • 5.79 kB
text/typescript
import fetch from 'node-fetch'
import {
Unit,
CountryCode,
Language,
QueryType,
InitialSettings,
Location,
SetCurrentWeatherByCityName,
GetByCityName,
GetByCityId,
GetByGeoCoordinates,
} from './types'
import { HOST, API_VERSION } from './helpers'
class OpenWeather {
private settings: InitialSettings
private BASE_URL: string
private location: Location
constructor({
apiKey,
units = 'imperial',
language = 'en',
}: InitialSettings) {
this.settings = {
apiKey,
units,
language,
}
this.location = {
city: {},
cityId: undefined,
geoCoordinates: {},
zipcode: {},
}
this.BASE_URL = HOST + API_VERSION
}
// ***
// ***
// Setters
// ***
// ***
public setApiKey(apiKey: string) {
this.settings.apiKey = apiKey
}
public setUnits(units: Unit) {
this.settings.units = units
}
public setLanguage(language: Language) {
this.settings.language = language
}
public setCityName({
cityName,
state,
countryCode,
}: SetCurrentWeatherByCityName) {
this.location.city = {
...this.location.city,
cityName,
state,
countryCode,
}
}
public setCityId(cityId: number) {
this.location.cityId = cityId
}
public setGeoCoordinates(latitude: number, longitude: number) {
this.location.geoCoordinates = {
...this.location.geoCoordinates,
latitude,
longitude,
}
}
public setZipCode(zipcode: number, countryCode?: CountryCode) {
this.location.zipcode = {
...this.location.zipcode,
zipcode,
countryCode,
}
}
public clearSettings() {
this.settings = {
apiKey: 'youNeedValidApiKey',
units: 'imperial',
language: 'en',
}
}
public clearLocation() {
this.location = {
city: {},
cityId: undefined,
geoCoordinates: {},
zipcode: {},
}
}
// ***
// ***
// Getters
// ***
// ***
public getAllSettings() {
return this.settings
}
public getAllLocations() {
return this.location
}
// ***
// ***
// Private
// ***
// ***
private buildURL(queryType: QueryType, query: string) {
const { BASE_URL, settings } = this
return `${BASE_URL + queryType}?${query}&appid=${settings.apiKey}`
}
// ***
// ***
// protected
// ***
// ***
protected getByCityName({ location, queryType }: GetByCityName) {
return new Promise(async (resolve, reject) => {
try {
if (!location?.cityName && !this.location.city.cityName) {
throw new Error(
`cityName missing, please pass it via argument or set it using setCityName method`
)
}
const cityName = location?.cityName || this.location.city.cityName
const state = location?.state || this.location.city.state
const countryCode =
location?.countryCode || this.location.city.countryCode
const query = `q=${cityName}${state ? ',' + state : ''}${
countryCode ? ',' + countryCode : ''
}`
const request = this.buildURL(queryType, query)
const response = await fetch(request)
const currentWeather = await response.json()
resolve(currentWeather)
} catch (error) {
reject(error)
}
})
}
protected getByCityId({ cityId, queryType }: GetByCityId) {
return new Promise(async (resolve, reject) => {
try {
const { location } = this
if (!cityId && !location.cityId) {
throw new Error(
`cityId missing, please pass it via argument or set it using setCityId method`
)
}
cityId = cityId || location.cityId
const query = `id=${cityId}`
const request = this.buildURL(queryType, query)
const response = await fetch(request)
const currentWeather = await response.json()
resolve(currentWeather)
} catch (error) {
reject(error)
}
})
}
protected getByGeoCoordinates({
latitude,
longitude,
queryType,
}: GetByGeoCoordinates) {
return new Promise(async (resolve, reject) => {
try {
if (
(!latitude || !longitude) &&
(!this.location.geoCoordinates.latitude ||
!this.location.geoCoordinates.longitude)
) {
throw new Error(
`latitude or longitude missing, please pass it via argument or set it using setGeoCoordinates method`
)
}
latitude = latitude || this.location.geoCoordinates.latitude
longitude = longitude || this.location.geoCoordinates.longitude
const query = `lat=${latitude}&lon=${longitude}`
const request = this.buildURL(queryType, query)
const response = await fetch(request)
const currentWeather = await response.json()
resolve(currentWeather)
} catch (error) {
reject(error)
}
})
}
protected getByZipcode(
zipcode: number,
queryType: QueryType,
countryCode?: CountryCode
) {
return new Promise(async (resolve, reject) => {
try {
const { location } = this
if (!zipcode && !location.zipcode.zipcode) {
throw new Error(
`zipcode missing, please pass it via argument or set it using setZipcode method`
)
}
zipcode = zipcode || location.zipcode.zipcode
const query = `zip=${zipcode}${countryCode ? ',' + countryCode : ''}`
const request = this.buildURL(queryType, query)
const response = await fetch(request)
const currentWeather = await response.json()
resolve(currentWeather)
} catch (error) {
reject(error)
}
})
}
}
export default OpenWeather