mirror of
https://github.com/zhigang1992/notion-api-worker.git
synced 2026-01-12 17:32:42 +08:00
Resolve users from table
This commit is contained in:
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
36
src/index.ts
36
src/index.ts
@@ -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) => {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
30
src/types.d.ts
vendored
Normal 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;
|
||||
Reference in New Issue
Block a user