Skip to content

Commit

Permalink
Adds Announcement API
Browse files Browse the repository at this point in the history
  • Loading branch information
Robert27 committed Apr 9, 2024
1 parent d118730 commit cf1c974
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 51 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install modules
run: npm install
- name: Run ESLint
run: npx eslint . --ext .js,.jsx,.ts,.tsx
- name: Run Prettier
run: npx prettier --check .
11 changes: 11 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { ApolloServer } from '@apollo/server'
import {
ApolloServerPluginLandingPageLocalDefault,
ApolloServerPluginLandingPageProductionDefault,
} from '@apollo/server/plugin/landingPage/default'
import { apolloIntegration } from '@chrisenglert/as-integrations-bun'
import NodeCache from 'node-cache'

Expand All @@ -8,6 +12,13 @@ import { typeDefs } from './src/schema'
const apolloServer = new ApolloServer({
typeDefs,
resolvers,
plugins: [
process.env.NODE_ENV === 'production'
? ApolloServerPluginLandingPageProductionDefault({
footer: false,
})
: ApolloServerPluginLandingPageLocalDefault(),
],
})

export const cache = new NodeCache({ stdTTL: 60 * 10 })
Expand Down
18 changes: 18 additions & 0 deletions src/data/demo-data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"announcements": [
{
"title": {
"de": "Infoveranstaltung",
"en": "Information event"
},
"description": {
"de": "Neuland Ingolstadt e.V. lädt ein zur Infoveranstaltung am 10.04.2024 um 18:00 Uhr. Hier erfährst du alles über Neuland, unsere Projekte und wie du dich einbringen kannst.",
"en": "Neuland Ingolstadt e.V. invites you to the information event on 10.04.2024 at 6:00 p.m. Here you will learn everything about Neuland, our projects and how you can get involved."
},
"startDateTime": "2024-04-06T00:00:00",
"endDateTime": "2024-04-10T18:00:00",
"priority": 1,
"url": "https://neuland-ingolstadt.de"
}
]
}
17 changes: 17 additions & 0 deletions src/resolvers/announcements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import demoData from '@/data/demo-data.json'
import fs from 'fs/promises'

const dataStore = `${process.env.STORE}/announcements.json`
const isDev = process.env.NODE_ENV !== 'production'

/**
* Announcement data.
* In development mode, this will return demo data.
*/
export async function announcements(): Promise<Announcement[]> {
if (isDev) {
return demoData.announcements
}
const data = await fs.readFile(dataStore)
return JSON.parse(data.toString())
}
58 changes: 7 additions & 51 deletions src/resolvers/charging.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,13 @@
import staticData from '@/data/mobility.json'
import { getCharging } from '@/scraping/charging'

import { cache } from '../..'

const URL =
'https://app.chargecloud.de/emobility:ocpi/7d25c525838f55d21766c0dfee5ad21f/app/2.0/locations?swlat=48.7555&swlng=11.4146&nelat=48.7767&nelng=11.4439'
export const charging = async (): Promise<ChargingData[]> => {
try {
const data = cache.get<ChargingData[]>('chargingStations')
if (data == null) {
const resp = await fetch(URL)
const data = await resp.json()
if (resp.status !== 200) {
throw new Error('Charging station data not available')
}
const result = data.data.map(
(entry: {
id: any
name: string
address: any
city: any
coordinates: { latitude: any; longitude: any }
evses: {
filter: (arg0: (x: any) => boolean) => {
(): any
new (): any
length: any
}
length: any
}
operator: { name: any }
}) => ({
id: entry.id,
name: entry.name.trim(),
address: entry.address,
city: entry.city,
latitude: entry.coordinates.latitude,
longitude: entry.coordinates.longitude,
operator: entry.operator.name,
available: entry.evses.filter(
(x) => x.status === 'AVAILABLE'
).length,
total: entry.evses.length,
freeParking:
staticData.charging.find((x) => x.id === entry.id)
?.freeParking ?? null,
})
)
cache.set('chargingStations', result, 60)
return result
}
return data
} catch (e) {
console.error(e)
throw new Error('Charging station data not available')
const data = cache.get<ChargingData[]>('chargingStations')
if (data == null) {
const result = await getCharging()
cache.set('chargingStations', result, 60)
return result
}
return data
}
2 changes: 2 additions & 0 deletions src/resolvers/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { announcements } from './announcements'
import { bus } from './bus'
import { charging } from './charging'
import { clEvents } from './cl-events'
Expand All @@ -13,5 +14,6 @@ export const resolvers = {
clEvents,
bus,
train,
announcements,
},
}
17 changes: 17 additions & 0 deletions src/schema/query/announcements.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import gql from 'graphql-tag'

export const announcementsType = gql`
type Announcement {
title: MultiLanguageString!
description: MultiLanguageString!
startDateTime: String!
endDateTime: String!
priority: Int!
url: String
}
type MultiLanguageString {
de: String
en: String
}
`
3 changes: 3 additions & 0 deletions src/schema/query/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import gql from 'graphql-tag'

import { announcementsType } from './announcements'
import { busType } from './bus'
import { chargingType } from './charging'
import { clEventsType } from './cl-events'
Expand All @@ -14,6 +15,7 @@ export const queryType = gql`
${clEventsType}
${busType}
${trainType}
${announcementsType}
"Root query"
type Query {
parking: ParkingData
Expand All @@ -22,5 +24,6 @@ export const queryType = gql`
clEvents: [ClEvent!]!
bus(station: String!): [Bus!]!
train(station: String!): [Train!]!
announcements: [Announcement!]!
}
`
52 changes: 52 additions & 0 deletions src/scraping/charging.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import staticData from '@/data/mobility.json'

const URL =
'https://app.chargecloud.de/emobility:ocpi/7d25c525838f55d21766c0dfee5ad21f/app/2.0/locations?swlat=48.7555&swlng=11.4146&nelat=48.7767&nelng=11.4439'

export const getCharging = async (): Promise<ChargingData[]> => {
try {
const resp = await fetch(URL)
const data = await resp.json()
if (resp.status !== 200) {
throw new Error('Charging station data not available')
}
const result = data.data.map(
(entry: {
id: number
name: string
address: string
city: string
coordinates: { latitude: number; longitude: number }
evses: {
filter: (arg0: (x: any) => boolean) => {
(): number
new (): number
length: number
}
length: number
}
operator: { name: string }
}) => ({
id: entry.id,
name: entry.name.trim(),
address: entry.address,
city: entry.city,
latitude: entry.coordinates.latitude,
longitude: entry.coordinates.longitude,
operator: entry.operator.name,
available: entry.evses.filter((x) => x.status === 'AVAILABLE')
.length,
total: entry.evses.length,
freeParking:
staticData.charging.find(
(x) => (x.id as unknown as number) === entry.id
)?.freeParking ?? null,
})
)

return result
} catch (e) {
console.error(e)
throw new Error('Charging station data not available')
}
}
14 changes: 14 additions & 0 deletions src/types/announcement.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
interface Announcement {
title: {
de: string
en: string
}
description: {
de: string
en: string
}
startDateTime: string
endDateTime: string
priority: number
url: string | null
}
File renamed without changes.

0 comments on commit cf1c974

Please sign in to comment.