Skip to content

Commit 9363ae4

Browse files
author
hywax
committed
feat: openweathermap service
1 parent 2e98fdf commit 9363ae4

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed

components/Item.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ function resolveByTypeComponent(type: string) {
2828
return resolveComponent('ServiceIpApi')
2929
}
3030
31+
if (type === 'openweathermap') {
32+
return resolveComponent('ServiceOpenWeatherMap')
33+
}
34+
3135
return resolveComponent('ServiceBase')
3236
}
3337
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<template>
2+
<ServiceBase v-bind="props">
3+
<template #icon="{ service }">
4+
<ServiceBaseIcon :name="`wi:owm-${service?.data?.iconId}`" v-bind="iconProps" />
5+
</template>
6+
<template #title="{ service }">
7+
{{ service.data?.temp.toFixed(1) }} {{ metricSymbol }}
8+
</template>
9+
<template #description="{ service }">
10+
{{ service.data?.place ? `${service.data?.place},` : '' }} {{ service.data?.description }}
11+
</template>
12+
</ServiceBase>
13+
</template>
14+
15+
<script setup lang="ts">
16+
import type { OpenWeatherMapService, ServiceClient } from '~/types'
17+
18+
const props = defineProps<ServiceClient<OpenWeatherMapService>>()
19+
const iconProps = computed(() => {
20+
if (!props.icon) {
21+
return {}
22+
}
23+
24+
const { name: _, ...p } = props.icon
25+
26+
return p
27+
})
28+
const metricSymbol = computed(() => {
29+
if (props?.options?.units === 'imperial') {
30+
return '°F'
31+
}
32+
33+
return '°C'
34+
})
35+
</script>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { OpenWeatherMapService } from '~/types'
2+
import { getServiceWithDefaultData, returnServiceWithData } from '~/server/utils/services'
3+
4+
interface OWMResponse {
5+
main: {
6+
temp: number
7+
}
8+
name: string
9+
weather: {
10+
id: number
11+
description: string
12+
}[]
13+
}
14+
15+
const cachedOWMData = defineCachedFunction(async ({ lon, lat, units, apiKey, lang }: { lon: number, lat: number, units: string, apiKey: string, lang: string }) => {
16+
const response = await $fetch<OWMResponse>(`https://api.openweathermap.org/data/2.5/weather?lat=${lat}&lon=${lon}&appid=${apiKey}&units=${units}&lang=${lang}`)
17+
return {
18+
temp: response.main.temp,
19+
place: response.name,
20+
iconId: response.weather[0].id,
21+
description: response.weather[0].description,
22+
}
23+
}, { maxAge: 60 * 24, getKey: ({ lon, lat }) => `${lon}-${lat}` })
24+
25+
export default defineEventHandler(async (event) => {
26+
const service = await getServiceWithDefaultData<OpenWeatherMapService>(event)
27+
const config = await getLocalConfig()
28+
const { options, secrets } = service.config
29+
const owm = await cachedOWMData({
30+
lon: options.lon,
31+
lat: options.lat,
32+
units: options.units || 'metric',
33+
apiKey: secrets.apiKey,
34+
lang: config?.lang || 'en',
35+
})
36+
37+
return returnServiceWithData(service, owm)
38+
})

types/services.d.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,20 @@ export interface IpApiService extends Service {
5252
place: string
5353
}
5454
}
55+
56+
export interface OpenWeatherMapService extends Service {
57+
options: {
58+
lon: number
59+
lat: number
60+
units: 'metric' | 'imperial' | 'standard'
61+
}
62+
secrets: {
63+
apiKey: string
64+
}
65+
server: {
66+
temp: number
67+
place: string
68+
description: string
69+
iconId: number
70+
}
71+
}

0 commit comments

Comments
 (0)