notion-astro-loader
Version:
Notion loader for the Astro Content Layer API. It allows you to load pages from a Notion database then render them as pages in a collection.
154 lines (153 loc) • 5.24 kB
JavaScript
import { z } from "astro/zod";
import { externalPropertyResponse, filePropertyResponse } from "./file.js";
function propertySchema(type, schema) {
return z.object({
type: z.literal(type),
id: z.string(),
[type]: schema,
});
}
const userObjectResponse = z
.object({
id: z.string(),
object: z.literal("user"),
})
.passthrough();
const selectPropertyResponse = z.object({
id: z.string(),
name: z.string(),
color: z.string(),
});
const dateField = z.union([
z.string().date(),
z.string().datetime({ offset: true }),
]);
const dateResponse = z.object({
start: dateField,
end: dateField.nullable(),
time_zone: z.string().nullable(),
});
const formulaPropertyResponse = z.discriminatedUnion("type", [
z.object({
type: z.literal("string"),
string: z.string().nullable().nullable(),
}),
z.object({
type: z.literal("date"),
date: z.string().datetime({ offset: true }).nullable(),
}),
z.object({
type: z.literal("number"),
number: z.number().nullable(),
}),
z.object({
type: z.literal("boolean"),
boolean: z.boolean().nullable(),
}),
]);
const baseRickTextResponse = z.object({
annotations: z
.object({
bold: z.boolean(),
italic: z.boolean(),
strikethrough: z.boolean(),
underline: z.boolean(),
code: z.boolean(),
color: z.string(),
})
.passthrough(),
plain_text: z.string(),
href: z.string().nullable(),
});
const richTextItemResponse = z.discriminatedUnion("type", [
baseRickTextResponse.extend({
type: z.literal("text"),
text: z.object({
content: z.string(),
link: z
.object({
url: z.string(),
})
.nullable(),
}),
}),
baseRickTextResponse.extend({
type: z.literal("mention"),
mention: z
.object({
type: z.enum([
"user",
"date",
"link_preview",
"template_mention",
"page",
"database",
]),
})
.passthrough(),
}),
baseRickTextResponse.extend({
type: z.literal("equation"),
equation: z.object({
expression: z.string(),
}),
}),
]);
const relationResponse = z.object({ id: z.string() });
export const number = propertySchema("number", z.number().nullable());
export const url = propertySchema("url", z.string().nullable());
export const select = propertySchema("select", selectPropertyResponse.nullable());
export const multi_select = propertySchema("multi_select", z.array(selectPropertyResponse));
export const status = propertySchema("status", selectPropertyResponse.nullable());
export const date = propertySchema("date", dateResponse.nullable());
export const email = propertySchema("email", z.string().nullable());
export const phone_number = propertySchema("phone_number", z.string().nullable());
export const checkbox = propertySchema("checkbox", z.boolean());
export const files = propertySchema("files", z.array(z.discriminatedUnion("type", [
filePropertyResponse.extend({ name: z.string() }),
externalPropertyResponse.extend({ name: z.string() }),
])));
export const created_by = propertySchema("created_by", userObjectResponse);
export const created_time = propertySchema("created_time", z.string().datetime({ offset: true }));
export const last_edited_by = propertySchema("last_edited_by", userObjectResponse);
export const last_edited_time = propertySchema("last_edited_time", z.string().datetime({ offset: true }));
export const formula = propertySchema("formula", formulaPropertyResponse);
export const title = propertySchema("title", z.array(richTextItemResponse));
export const rich_text = propertySchema("rich_text", z.array(richTextItemResponse));
export const people = propertySchema("people", z.array(userObjectResponse));
export const relation = propertySchema("relation", z.array(relationResponse));
export const rollup = propertySchema("rollup", z.discriminatedUnion("type", [
z.object({
function: z.string(),
type: z.literal("number"),
number: z.number().nullable(),
}),
z.object({
function: z.string(),
type: z.literal("date"),
date: z.string().datetime({ offset: true }).nullable(),
}),
z.object({
function: z.string(),
type: z.literal("array"),
array: z.array(z.discriminatedUnion("type", [
z.object({
type: z.literal("title"),
title: z.array(richTextItemResponse),
}),
z.object({
type: z.literal("rich_text"),
rich_text: z.array(richTextItemResponse),
}),
z.object({
type: z.literal("people"),
people: z.array(userObjectResponse),
}),
z.object({
type: z.literal("relation"),
relation: z.array(relationResponse),
}),
])),
}),
]));
export const unique_id = propertySchema("unique_id", z.any());