feat: metaculus fetcher skips unknown types instead of failing
This commit is contained in:
parent
646397d8d4
commit
5bf24a58ef
|
@ -88,7 +88,7 @@ const optionalPageProps = {
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const apiQuestionSchema = {
|
const questionSchema = {
|
||||||
discriminator: "type",
|
discriminator: "type",
|
||||||
mapping: {
|
mapping: {
|
||||||
forecast: {
|
forecast: {
|
||||||
|
@ -141,10 +141,19 @@ const apiQuestionSchema = {
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
const apiMultipleQuestionsSchema = {
|
const knownQuestionTypes = Object.keys(questionSchema.mapping);
|
||||||
|
|
||||||
|
const shallowMultipleQuestionsSchema = {
|
||||||
properties: {
|
properties: {
|
||||||
results: {
|
results: {
|
||||||
elements: apiQuestionSchema,
|
elements: {
|
||||||
|
properties: {
|
||||||
|
type: {
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
additionalProperties: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
next: {
|
next: {
|
||||||
type: "string",
|
type: "string",
|
||||||
|
@ -160,15 +169,22 @@ export type ApiCommon = JTDDataType<{
|
||||||
export type ApiPredictable = JTDDataType<{
|
export type ApiPredictable = JTDDataType<{
|
||||||
properties: typeof predictableProps;
|
properties: typeof predictableProps;
|
||||||
}>;
|
}>;
|
||||||
export type ApiQuestion = JTDDataType<typeof apiQuestionSchema>;
|
export type ApiQuestion = JTDDataType<typeof questionSchema>;
|
||||||
export type ApiMultipleQuestions = JTDDataType<
|
|
||||||
typeof apiMultipleQuestionsSchema
|
type ApiShallowMultipleQuestions = JTDDataType<
|
||||||
|
typeof shallowMultipleQuestionsSchema
|
||||||
>;
|
>;
|
||||||
|
|
||||||
const validateApiQuestion = new Ajv().compile<ApiQuestion>(apiQuestionSchema);
|
export type ApiMultipleQuestions = {
|
||||||
const validateApiMultipleQuestions = new Ajv().compile<ApiMultipleQuestions>(
|
results: ApiQuestion[];
|
||||||
apiMultipleQuestionsSchema
|
next: ApiShallowMultipleQuestions["next"]; // Omit<ApiShallowMultipleQuestions, "results"> doesn't work correctly here
|
||||||
);
|
};
|
||||||
|
|
||||||
|
const validateQuestion = new Ajv().compile<ApiQuestion>(questionSchema);
|
||||||
|
const validateShallowMultipleQuestions =
|
||||||
|
new Ajv().compile<ApiShallowMultipleQuestions>(
|
||||||
|
shallowMultipleQuestionsSchema
|
||||||
|
);
|
||||||
|
|
||||||
async function fetchWithRetries<T = unknown>(url: string): Promise<T> {
|
async function fetchWithRetries<T = unknown>(url: string): Promise<T> {
|
||||||
try {
|
try {
|
||||||
|
@ -209,12 +225,35 @@ const fetchAndValidate = async <T = unknown>(
|
||||||
export async function fetchApiQuestions(
|
export async function fetchApiQuestions(
|
||||||
next: string
|
next: string
|
||||||
): Promise<ApiMultipleQuestions> {
|
): Promise<ApiMultipleQuestions> {
|
||||||
return await fetchAndValidate(next, validateApiMultipleQuestions);
|
const data = await fetchAndValidate(next, validateShallowMultipleQuestions);
|
||||||
|
|
||||||
|
const isDefined = <T>(argument: T | undefined): argument is T => {
|
||||||
|
return argument !== undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
results: data.results
|
||||||
|
.map((result) => {
|
||||||
|
if (!knownQuestionTypes.includes(result.type)) {
|
||||||
|
console.warn(`Unknown result type ${result.type}, skipping`);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
if (!validateQuestion(result)) {
|
||||||
|
throw new Error(
|
||||||
|
`Response validation failed: ` +
|
||||||
|
JSON.stringify(validateQuestion.errors)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
.filter(isDefined),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetchSingleApiQuestion(id: number): Promise<ApiQuestion> {
|
export async function fetchSingleApiQuestion(id: number): Promise<ApiQuestion> {
|
||||||
return await fetchAndValidate(
|
return await fetchAndValidate(
|
||||||
`https://www.metaculus.com/api2/questions/${id}/`,
|
`https://www.metaculus.com/api2/questions/${id}/`,
|
||||||
validateApiQuestion
|
validateQuestion
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user