Resolve users from table

This commit is contained in:
Tobias Lins
2020-04-21 19:05:18 +02:00
parent acae23aa9e
commit d33cc0c786
8 changed files with 97 additions and 28 deletions

View File

@@ -1,5 +1,3 @@
import { resolve } from "dns";
const NOTION_API = "https://www.notion.so/api/v3";
type JSONData =
@@ -29,7 +27,6 @@ const fetchNotionData = async ({ resource, body }: INotionParams) => {
"content-type": "application/json",
},
body: JSON.stringify(body),
//cf: {}
});
return res.json();
@@ -74,7 +71,7 @@ export const fetchTableData = async (
return table;
};
export const fetchNotionUser = async (
export const fetchNotionUsers = async (
userIds: string[]
): Promise<{ id: string; full_name: string }[]> => {
const users = await fetchNotionData({
@@ -83,11 +80,13 @@ export const fetchNotionUser = async (
requests: userIds.map((id) => ({ id, table: "notion_user" })),
},
});
return users.results.map((u: any) => {
const user = {
id: u.value.id,
full_name: u.value.given_name + " " + u.value.family_name,
firstName: u.value.given_name,
lastLame: u.value.family_name,
fullName: u.value.given_name + " " + u.value.family_name,
profilePhoto: u.value.profile_photo,
};
return user;
});

View File

@@ -41,12 +41,15 @@ export type ColumnSchemaType = {
type: ColumnType;
};
type UserType = { id: string; full_name: string };
export type RowContentType =
| string
| boolean
| number
| string[]
| { title: string; id: string };
| { title: string; id: string }
| UserType[];
export interface BaseValueType {
id: string;

View File

@@ -31,7 +31,7 @@ export const getNotionValue = (
case "select":
return val[0][0];
case "multi_select":
return val[0] as string[];
return val[0][0].split(",") as string[];
case "number":
return Number(val[0][0]);
default:

View File

@@ -1,11 +1,13 @@
import {} from "@cloudflare/workers-types";
import { Router, Method } from "tiny-request-router";
import { Router, Method, Params } from "tiny-request-router";
import { pageRoute } from "./routes/page";
import { tableRoute } from "./routes/table";
import { userRoute } from "./routes/user";
const router = new Router();
export type Handler = (params: Params) => Promise<Response> | Response;
const router = new Router<Handler>();
router.options("*", () => new Response("", { headers: {} }));
router.get("/v1/page/:pageId", pageRoute);
@@ -14,16 +16,19 @@ router.get("/v1/user/:userId", userRoute);
router.get(
"*",
async (event: FetchEvent) =>
async () =>
new Response(
`Route not found!
Available routes:
- /v1/page/:pageId
- /v1/table/:pageId`,
- /v1/table/:pageId
- /v1/user/:pageId`,
{ status: 404 }
)
);
const cache = (caches as any).default;
const handleRequest = async (fetchEvent: FetchEvent): Promise<Response> => {
const request = fetchEvent.request;
const { pathname } = new URL(request.url);
@@ -34,7 +39,28 @@ const handleRequest = async (fetchEvent: FetchEvent): Promise<Response> => {
return new Response("Endpoint not found.", { status: 404 });
}
return match.handler(match.params);
const cacheKey = request.url;
let response;
try {
const cachedResponse = await cache.match(cacheKey);
if (cachedResponse) {
response = cachedResponse;
}
} catch (err) {}
const getResponseAndPersist = async () => {
const res = await match.handler(match.params);
await cache.put(cacheKey, res.clone());
return res;
};
if (response) {
fetchEvent.waitUntil(getResponseAndPersist());
return response;
}
return getResponseAndPersist();
};
self.addEventListener("fetch", async (event: Event) => {

View File

@@ -1,8 +1,9 @@
import { Params } from "tiny-request-router";
import { fetchPageById } from "../api/notion";
import { parsePageId } from "../api/utils";
import { createResponse } from "../response";
export async function pageRoute(params: { pageId: string }) {
export async function pageRoute(params: Params) {
const pageId = parsePageId(params.pageId);
const res = await fetchPageById(pageId);

View File

@@ -1,13 +1,15 @@
import { fetchPageById, fetchTableData } from "../api/notion";
import { Params } from "tiny-request-router";
import { fetchPageById, fetchTableData, fetchNotionUsers } from "../api/notion";
import { parsePageId, getNotionValue } from "../api/utils";
import { RowContentType, CollectionType, RowType } from "../api/types";
import { createResponse } from "../response";
export async function tableRoute(params: { pageId: string }) {
export async function tableRoute(params: Params) {
const pageId = parsePageId(params.pageId);
const page = await fetchPageById(pageId);
console.log({ page });
if (!page.recordMap.collection)
return new Response("No table found on Notion page: " + pageId);
const collection: CollectionType = Object.keys(page.recordMap.collection).map(
(k) => page.recordMap.collection[k]
@@ -23,8 +25,6 @@ export async function tableRoute(params: { pageId: string }) {
collectionView.value.id
);
console.log({ table });
const collectionRows = collection.value.schema;
const collectionColKeys = Object.keys(collectionRows);
@@ -37,17 +37,26 @@ export async function tableRoute(params: { pageId: string }) {
b.value && b.value.properties && b.value.parent_id === collection.value.id
);
const rows = tableData.map((td) => {
let row: { [key: string]: RowContentType } = { id: td.value.id };
collectionColKeys.forEach((key) => {
type Row = { id: string; [key: string]: RowContentType };
const rows: Row[] = [];
for (const td of tableData) {
let row: Row = { id: td.value.id };
for (const key of collectionColKeys) {
const val = td.value.properties[key];
if (val) {
const schema = collectionRows[key];
row[schema.name] = getNotionValue(val, schema.type);
if (schema.type === "person") {
const users = await fetchNotionUsers(row[schema.name] as string[]);
row[schema.name] = users;
}
}
});
return row;
});
}
rows.push(row);
}
return createResponse(JSON.stringify(rows));
}

View File

@@ -1,8 +1,9 @@
import { fetchNotionUser } from "../api/notion";
import { Params } from "tiny-request-router";
import { fetchNotionUsers } from "../api/notion";
import { createResponse } from "../response";
export async function userRoute(params: { userId: string }) {
const users = await fetchNotionUser([params.userId]);
export async function userRoute(params: Params) {
const users = await fetchNotionUsers([params.userId]);
return createResponse(JSON.stringify(users[0]));
}

30
src/types.d.ts vendored Normal file
View File

@@ -0,0 +1,30 @@
interface CacheOptions {
/**
* Consider the request method a GET regardless of its actual value.
*/
ignoreMethod?: boolean;
}
export interface Caches {
default: {
/**
* Adds to the cache a response keyed to the given request.
* Returns a promise that resolves to undefined once the cache stores the response.
*/
put(request: Request | string, response: Response): Promise<undefined>;
/**
* Returns a promise wrapping the response object keyed to that request.
*/
match(
request: Request | string,
options?: CacheOptions
): Promise<Response | undefined>;
/**
* Deletes the Response object from the cache and
* returns a Promise for a Boolean response
*/
delete(request: Request | string, options?: CacheOptions): Promise<boolean>;
};
}
declare let caches: Caches;