Skip to content

Commit

Permalink
refactor: Made the parsing of the API Responses more generic
Browse files Browse the repository at this point in the history
  • Loading branch information
FleetAdmiralJakob committed Jan 17, 2024
1 parent d75023e commit 5ae17ac
Showing 1 changed file with 89 additions and 131 deletions.
220 changes: 89 additions & 131 deletions packages/api/src/routers/weather.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import axios from "axios";
import axios, { AxiosResponse } from "axios";
import dayjs from "dayjs";
import timezone from "dayjs/plugin/timezone";
import utc from "dayjs/plugin/utc";
Expand Down Expand Up @@ -132,21 +132,23 @@ const MoonPhaseSchema = z.object({
type MoonPhase = z.infer<typeof MoonPhaseSchema> | undefined;

const WarningSchema = z.object({
warning: z.array(
z.object({
sender: z.string(),
pubTime: z.string(),
title: z.string(),
startTime: z.string(),
endTime: z.string(),
status: z.string(),
level: z.string(),
severity: z.string(),
urgency: z.string(),
certainty: z.string(),
text: z.string(),
}),
),
warning: z
.array(
z.object({
sender: z.string(),
pubTime: z.string(),
title: z.string(),
startTime: z.string(),
endTime: z.string(),
status: z.string(),
level: z.string(),
severity: z.string(),
urgency: z.string(),
certainty: z.string(),
text: z.string(),
}),
)
.optional(),
});

type Warning = z.infer<typeof WarningSchema> | undefined;
Expand Down Expand Up @@ -241,71 +243,75 @@ export const weatherRouter = createTRPCRouter({
let moonPhase: MoonPhase = undefined;
let warning: Warning = undefined;

if (hourlyResult.status === "fulfilled") {
try {
const data = hourlyResult.value.data;
function handleApiResponse<DataSchema>(
result: PromiseSettledResult<AxiosResponse<DataSchema>>,
schema: z.ZodSchema<DataSchema>,
errorMessage: string,
filterFn?: (data: NonNullable<DataSchema>) => NonNullable<DataSchema>,
): DataSchema | undefined {
let parsedData: DataSchema | undefined = undefined;

if (!data) {
throw new Error("Air quality data is undefined");
if (result.status === "fulfilled") {
try {
let data = result.value.data;

if (!data) {
throw new Error(`The ${errorMessage} data is undefined`);
}

// Apply the filter function if it is provided
if (filterFn) {
data = filterFn(data);
}

parsedData = schema.parse(data);
} catch (error) {
if (error instanceof z.ZodError) {
log.error(`Zod Errors in the ${errorMessage}`, error.issues);
} else {
log.error(`Else Error in the ${errorMessage}`, { error });
}
}
} else {
log.error(`${errorMessage} request failed`, {
status: result.status,
reason:
typeof result.reason === "string"
? result.reason
: "The reason is not a string",
});
}

return parsedData;
}

hourlyAndDailyData = handleApiResponse<HourlyAndDailyWeather>(
hourlyResult,
HourlyAndDailyWeatherSchema,
"hourly weather",
(data) => {
// log.debug("Hourly data without the filter and unparsed", data);

data.hourly.precipitation_probability =
data.hourly.precipitation_probability.filter(
(value) => value !== null,
);

hourlyAndDailyData = HourlyAndDailyWeatherSchema.parse(data);
// log.debug("Parsed and filtered hourly data", hourlyAndDailyData);
} catch (error) {
if (error instanceof z.ZodError) {
log.error("Zod Errors in the hourly weather", error.issues);
} else {
log.error("Else Error in the hourly weather", { error });
}
}
} else {
log.error("Hourly weather data request failed", {
status: hourlyResult.status,
reason:
typeof hourlyResult.reason === "string"
? hourlyResult.reason
: "The reason is not a string",
});
}

if (presentWeatherResult.status === "fulfilled") {
try {
presentWeather = PresentWeatherSchema.parse(
presentWeatherResult.value.data,
);
// log.debug("Parsed present weather data", presentWeather);
} catch (error) {
if (error instanceof z.ZodError) {
log.error("Zod Errors in the present weather", error.issues);
} else {
log.error("Else Error in the present weather", { error });
}
}
} else {
log.error("Present weather data request failed", {
status: presentWeatherResult.status,
reason:
typeof presentWeatherResult.reason === "string"
? presentWeatherResult.reason
: "The reason is not a string",
});
}

if (presentAirQualityResult.status === "fulfilled") {
try {
const data = presentAirQualityResult.value.data;
return data;
},
);

if (!data) {
throw new Error("Air quality data is undefined");
}
presentWeather = handleApiResponse<PresentWeather>(
presentWeatherResult,
PresentWeatherSchema,
"present weather",
);

presentAirQuality = handleApiResponse<PresentAirQuality>(
presentAirQualityResult,
PresentAirQualitySchema,
"present air quality",
(data) => {
// log.debug("Air quality data without the filter and unparsed", data);

data.hourly.pm10 = data.hourly.pm10.filter((value) => value !== null);
Expand All @@ -316,69 +322,21 @@ export const weatherRouter = createTRPCRouter({
(value) => value !== null,
);

presentAirQuality = PresentAirQualitySchema.parse(data);
} catch (error) {
if (error instanceof z.ZodError) {
log.error("Zod Errors in the air quality", error.issues);
console.error("Air quality data without the filter", {
data: presentAirQualityResult.value.data,
});
} else {
log.error("Else Error in the air quality", { error });
}
}
} else {
log.error("Present air quality data request failed", {
status: presentAirQualityResult.status,
reason:
typeof presentAirQualityResult.reason === "string"
? presentAirQualityResult.reason
: "The reason is not a string",
});
}
return data;
},
);

if (moonPhaseResult.status === "fulfilled") {
try {
// console.debug(moonPhaseResult.value.data);
// console.debug(urlMoonPhase);
moonPhase = MoonPhaseSchema.parse(moonPhaseResult.value.data);
} catch (error) {
if (error instanceof z.ZodError) {
log.error("Zod Errors in the moon phase", error.issues);
console.debug("Moon phase data without the filter", {
data: moonPhaseResult.value.data,
});
console.debug("Moon phase data url", urlMoonPhase);
} else {
log.error("Else Error in the moon phase", { error });
}
}
} else {
log.error("Moon phase data request failed", {
status: moonPhaseResult.status,
reason:
typeof moonPhaseResult.reason === "string"
? moonPhaseResult.reason
: "The reason is not a string",
});
}
if (warningResult.status === "fulfilled") {
try {
// console.debug(warningResult.value.data);
// console.debug(urlWarning);
warning = WarningSchema.parse(warningResult.value.data);
} catch (error) {
if (error instanceof z.ZodError) {
log.error("Zod Errors in the warning", error.issues);
console.debug("Warning data without the filter", {
data: warningResult.value.data,
});
console.debug("Warning data url", urlWarning);
} else {
log.error("Else Error in the warning", { error });
}
}
}
moonPhase = handleApiResponse<MoonPhase>(
moonPhaseResult,
MoonPhaseSchema,
"moon phase",
);

warning = handleApiResponse<Warning>(
warningResult,
WarningSchema,
"warning",
);

let presentAirQualityIndex: number | undefined = undefined;

Expand Down

1 comment on commit 5ae17ac

@vercel
Copy link

@vercel vercel bot commented on 5ae17ac Jan 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.