@upstart.gg/sdk
Version:
You can test the CLI without recompiling by running:
247 lines (245 loc) • 7.74 kB
JavaScript
import { nanoid } from "nanoid";
import { Client } from "@notionhq/client";
//#region src/shared/datarecords/external/notion/handler.ts
const MAX_CALL = 10;
const MAX_PAGES = 1e3;
async function saveRecord({ formData, options, properties, accessToken }) {
const client = new Client({ auth: accessToken });
const notionData = buildCreatePageParameters(formData, options.properties);
try {
return client.pages.create({
parent: { database_id: options.id },
properties: { ...notionData }
});
} catch (e) {
return;
}
}
async function searchPages(client, pages, parameters, offset, resultIndex) {
const nextIndex = resultIndex ? resultIndex + 1 : 1;
if (nextIndex > (parameters?.maxCalls ?? MAX_CALL)) return {
status: "max_call_reached",
pages
};
try {
const response = await client.search({
filter: {
property: "object",
value: "page"
},
start_cursor: offset,
page_size: 100
});
if (!response) return {
status: "error",
pages
};
for (const d in response.results) {
const p = response.results[d];
if (p.parent.type !== "database_id") {
const page = {
id: p.id,
name: p.properties.title && p.properties.title.type === "title" && Array.isArray(p.properties.title.title) && p.properties.title.title[0]?.plain_text ? p.properties.title.title[0].plain_text : "No Title"
};
pages.push(page);
if (pages.length >= (parameters?.maxResults ?? MAX_PAGES)) return {
status: "max_pages_reached",
pages
};
}
}
if (response.has_more && response.next_cursor) {
const moreResults = await searchPages(client, pages, parameters, response.next_cursor, nextIndex);
if (moreResults.status !== "success") return {
status: moreResults.status,
pages
};
return moreResults;
}
} catch (error) {
console.error("Error searching Notion pages:", error);
}
return {
status: "success",
pages
};
}
async function listPages(accessToken, parameters) {
try {
const client = new Client({ auth: accessToken });
return await searchPages(client, [], { ...parameters });
} catch (error) {
console.error("Error listing Notion databases:", error);
throw error;
}
}
/**
* In Notion, databases column are sorted by alphabetical order
* @param schema
* @returns
*/
function buildDatabaseProperties(schemaProperties, requiredFields = []) {
const properties = {};
for (const [fieldName, field] of Object.entries(schemaProperties)) if (field.type === "string") if (fieldName in (requiredFields ?? []) && fieldName === "id") properties[fieldName] = {
title: {},
name: fieldName,
type: "title"
};
else if (field.format === "email") properties[fieldName] = {
type: "email",
name: fieldName,
email: {}
};
else if (field.format === "uri") properties[fieldName] = {
type: "url",
name: fieldName,
url: {}
};
else if (field.format === "date" || field.format === "date-time") properties[fieldName] = {
type: "date",
name: fieldName,
date: {}
};
else if (field.enum && Array.isArray(field.enum) && field.enum.length > 0) if (field.metadata?.["ui:widget"] === "checkbox") properties[fieldName] = {
type: "multi_select",
name: fieldName,
multi_select: { options: field.enum.map((option) => ({ name: option })) }
};
else properties[fieldName] = {
type: "select",
name: fieldName,
select: { options: field.enum.map((option) => ({ name: option })) }
};
else properties[fieldName] = {
rich_text: {},
name: fieldName,
type: "rich_text"
};
else if (field.type === "number") properties[fieldName] = { number: {} };
else if (field.type === "boolean") properties[fieldName] = { checkbox: {} };
if (!properties.id) properties.id = {
title: {},
name: "id",
type: "title"
};
return properties;
}
async function updateTable({ id, newName, newProperties, accessToken }) {
const client = new Client({ auth: accessToken });
const properties = newProperties ? buildDatabaseProperties(newProperties) : {};
const response = await client.databases.update({
database_id: id,
...newName ? { title: [{
type: "text",
text: { content: newName }
}] } : {},
...Object.keys(properties).length > 0 ? { properties } : {}
});
if (!response) throw new Error("Failed to update Notion database");
return {
id: response.id,
name: response.title[0]?.plain_text,
properties: response.properties,
url: response.url
};
}
async function createTable({ name, schema, pageId, accessToken }) {
const properties = buildDatabaseProperties(schema.properties, schema.required);
const data = {
parent: {
type: "page_id",
page_id: pageId
},
title: [{
type: "text",
text: { content: name }
}],
properties
};
const client = new Client({ auth: accessToken });
const response = await client.databases.create(data);
if (!response) throw new Error("Failed to create Notion database");
const table = await client.databases.retrieve({ database_id: response.id });
if (!table) throw new Error("Failed to retrieve Notion database after creation");
return {
id: table.id,
name: table.title[0]?.plain_text,
properties: table.properties,
url: table.url
};
}
async function checkPage({ pageId, accessToken }) {
const client = new Client({ auth: accessToken });
try {
const response = await client.pages.retrieve({ page_id: pageId });
if (!response) {
console.log("Failed to retrieve Notion page");
return;
}
if (response) {
const page = response;
return {
id: page.id,
name: page.properties.title && page.properties.title.type === "title" && Array.isArray(page.properties.title.title) && page.properties.title.title[0]?.plain_text ? page.properties.title.title[0].plain_text : "No Title"
};
}
} catch (e) {
console.error("Error retrieving Notion page:", e);
}
}
function buildCreatePageParameters(data, databaseProperties) {
const notionData = {};
for (const [key, value] of data.entries()) {
if (value === null || value === void 0 || value === "") continue;
if (key in databaseProperties) switch (databaseProperties[key].type) {
case "title":
notionData[key] = { title: [{ text: { content: String(value) } }] };
break;
case "rich_text":
notionData[key] = { rich_text: [{ text: { content: String(value) } }] };
break;
case "email":
notionData[key] = { email: String(value) };
break;
case "phone_number":
notionData[key] = { phone_number: String(value) };
break;
case "url":
notionData[key] = { url: String(value) };
break;
case "number":
notionData[key] = { number: Number(value) };
break;
case "checkbox":
notionData[key] = { checkbox: value === "true" || value === "1" };
break;
case "date":
notionData[key] = { date: value ? { start: String(value) } : null };
break;
case "select":
notionData[key] = { select: { name: String(value) } };
break;
case "multi_select": {
const getValues = (value$1) => {
if (value$1.startsWith("[") && value$1.endsWith("]")) try {
return JSON.parse(value$1);
} catch {
return [value$1];
}
if (value$1.includes(",")) return value$1.split(",").map((v) => v.trim()).filter((v) => v.length > 0);
return [value$1];
};
notionData[key] = { multi_select: getValues(String(value)).map((v) => ({ name: v })) };
break;
}
default:
console.warn(`Unsupported property type for key "${key}": ${databaseProperties[key].type}`);
notionData[key] = { rich_text: [{ text: { content: String(value) } }] };
}
}
if (!("id" in notionData)) notionData.id = { title: [{ text: { content: nanoid(5) } }] };
return notionData;
}
//#endregion
export { checkPage, createTable, listPages, saveRecord, updateTable };
//# sourceMappingURL=handler.js.map