@pagenote/notion-database
Version:
make notion as a real-database for server
302 lines • 13 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const client_1 = require("@notionhq/client");
const Table_1 = require("./Table");
const util_1 = require("./transformer/util");
const utils_1 = require("./common/utils");
const const_1 = require("./common/const");
const page_1 = require("./notion-helper/page");
class Database {
constructor(props) {
this.tables = new Map();
this.basePage = null;
this.lastSyncAt = 0;
this.props = props;
this.notion = new client_1.Client({
auth: props.token
});
this.onError = (databaseId, reason) => {
this.props.onError && this.props.onError(databaseId, reason);
};
}
/* 刷新设置项*/
refreshOption(props) {
this.props = Object.assign(Object.assign({}, this.props), props);
this.notion = new client_1.Client({
auth: props.token
});
// 清空 notion 配置(退出后清空基础页面、表列表)
if (!this.props.token) {
this.basePage = null;
this.tables.clear();
}
return this.ready();
}
ready() {
return Promise.all([this._initBasePage(), this._fetchTables()]).then(() => {
return this;
});
}
/**
* 初始化基础页面(根页面),没有的情况下,影响新建表,不影响存量表使用
*/
_initBasePage() {
var _a, _b, _c, _d, _e, _f;
return __awaiter(this, void 0, void 0, function* () {
// 1. 已有基础页信息时,直接返回
if ((_a = this.basePage) === null || _a === void 0 ? void 0 : _a.id) {
return Promise.resolve((_b = this.basePage) === null || _b === void 0 ? void 0 : _b.id);
}
// 2. 没有基础页信时,直接返回不拉取
const pageId = this.props.pageId;
if (!pageId) {
return Promise.resolve('');
}
// 3. 从 notion 中拉取基础页信息
this.basePage = (yield this.notion.pages.retrieve({
page_id: pageId
}));
const basePageId = ((_c = this.basePage) === null || _c === void 0 ? void 0 : _c.id) || '';
/*更新基础页信息,表明已联通*/
// @ts-ignore
if (((_f = (_e = (_d = this.basePage) === null || _d === void 0 ? void 0 : _d.icon) === null || _e === void 0 ? void 0 : _e.external) === null || _f === void 0 ? void 0 : _f.url) !== const_1.PAGENOTE_DB_ICON) {
(0, page_1.updatePageInfo)(this.notion, basePageId, {
icon: const_1.PAGENOTE_DB_ICON,
cover: const_1.PAGENOTE_DN_COVER
});
}
return basePageId;
});
}
/**
* 初始化授权页面下的所有表
*/
_fetchTables() {
const { token } = this.props;
const that = this;
// TODO 定期观察 notion SDK 有没有优化search方法,已更好的进行搜索,避免业务代码里的逻辑过滤判断
return this.notion
.search({
query: '[',
filter: {
property: 'object',
value: 'database' // 只拉取类型为 database 的页面
},
sort: {
timestamp: 'last_edited_time',
direction: 'ascending' // 按时间顺序,后则覆盖前者
}
})
.then(res => {
// TODO 拉取完所有表格 res.has_more
const databaseList = (res.results || []);
databaseList.forEach(item => {
var _a, _b, _c, _d;
if (item.archived) {
console.warn('has find the database is archived', item.url);
return;
}
/**
* 父节点必须是页面,否则无法获取其父节点
*/
if (item.parent.type !== 'page_id') {
return;
}
// 根据 notion 名称,获取一个语义化的表名
const tableName = (0, utils_1.getTableName)((0, util_1.resolveNotionRichTextItemRequest)(item.title));
const tempParentPageId = (0, utils_1.simpleFyId)(((_a = item === null || item === void 0 ? void 0 : item.parent) === null || _a === void 0 ? void 0 : _a.page_id) || '');
// 非根页面的表格不处理
if (((_b = this.basePage) === null || _b === void 0 ? void 0 : _b.id) &&
(0, utils_1.simpleFyId)(this.basePage.id) !== tempParentPageId) {
return;
}
const currentTable = new Table_1.default({
demoData: null,
onError: this.onError,
database_id: item.id,
cloudDescribe: item.properties,
token: token,
notion: this.notion,
parentPageId: tempParentPageId
});
/*如果已存在旧表,做出提示*/
const oldTable = that._getTable(tableName);
if (oldTable && oldTable.shortDatabaseId !== (0, utils_1.simpleFyId)(item.id)) {
// 添加表重名提示
;
[oldTable.shortDatabaseId, item.id].forEach(databaseId => {
(0, page_1.updateTableInfo)(this.notion, databaseId, {
emoji: const_1.TableEmoji.error,
description: `存在重名表格,请检查删除保留一个名为[${tableName}]的表格页面。`
});
});
(_c = this.props) === null || _c === void 0 ? void 0 : _c.onError(item.id || tableName || '', 'duplicate table name' + tableName);
}
else {
// @ts-ignore
if (((_d = item === null || item === void 0 ? void 0 : item.icon) === null || _d === void 0 ? void 0 : _d.emoji) !== const_1.TableEmoji.success) {
(0, page_1.updateTableInfo)(this.notion, item.id, {
emoji: const_1.TableEmoji.success,
description: `此表正在被 api 读写,请勿修改表结构、移动页面位置。你应该尽量不操作被托管的表格,否则可能导致无法恢复的异常。` // TODO 传参tips
});
}
}
/*赋值最新table*/
that._setTable(tableName, currentTable);
});
return that.tables;
});
}
_setTable(tableName, table) {
if (!tableName) {
return;
}
this.tables.set(tableName, table);
this.tables.set((0, utils_1.simpleFyId)(table.shortDatabaseId), table);
}
_getTable(tableNameOrId) {
return (this.tables.get(tableNameOrId) ||
this.tables.get((0, utils_1.simpleFyId)(tableNameOrId)));
}
/*异步获取 table */
getTableAsync(tableName, createOnNoTableByInitData) {
return __awaiter(this, void 0, void 0, function* () {
if (!tableName) {
console.trace('getTable error');
throw Error('tableName is required');
}
const that = this;
function createNewTable() {
if (createOnNoTableByInitData) {
return that.createTable(tableName, {
demoData: createOnNoTableByInitData
});
}
else {
throw Error('did not found this table: ' + tableName);
}
}
/*未初始化过DB表时*/
if (this.tables.size === 0) {
/*初始化所有表格后,返回表,无表时,直接创建新表*/
return this.ready().then(() => {
const table = this._getTable(tableName);
if (table) {
if (createOnNoTableByInitData) {
table._setDemoData(createOnNoTableByInitData);
}
return table;
}
else {
return createNewTable();
}
});
}
/*已初始化过,直接返回表格*/
const table = this._getTable(tableName);
if (table) {
if (createOnNoTableByInitData) {
table._setDemoData(createOnNoTableByInitData);
}
return Promise.resolve(table);
}
else {
return createNewTable();
}
});
}
/*同步获取 table,适用于确定目标 table 一定存在的情况下,具有前置执行的能力,表的状态信息后置补充*/
getTableSync(tableName, databaseId, demoData) {
const cacheTable = this._getTable(tableName) || this._getTable(databaseId);
if (cacheTable) {
return cacheTable;
}
else {
const table = new Table_1.default({
demoData: demoData,
notion: this.notion,
database_id: databaseId,
cloudDescribe: null,
token: this.props.token,
onError: this.onError,
parentPageId: ''
});
return table;
}
}
createTable(tableName, option) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const { token } = this.props;
const { properties, demoData } = option;
const notionProperties = properties || (0, util_1.defineNotionPropertySchemaByData)(demoData, true);
// 缓存表查询
if (this._getTable(tableName)) {
throw Error('table already exist');
}
// 实时表 唯一性保证
const currentTables = yield this._fetchTables();
if (currentTables.get(tableName)) {
throw Error('已存在表' + tableName);
}
// 无根页面,无法创建新表格
let tableRootPageId = ((_a = this.basePage) === null || _a === void 0 ? void 0 : _a.id) || '';
if (!tableRootPageId) {
tableRootPageId = yield this._initBasePage();
}
if (!tableRootPageId) {
throw Error('unknown root page_id');
}
return this.notion.databases
.create({
// V2 支持
description: [
{
text: {
content: `当前表格正在供读取。请勿修改表名[${tableName}]、请勿修改表结构。表结构变化可能导致无法正确读取此表数据,谨慎操作。`
}
}
],
is_inline: false,
cover: { external: { url: const_1.PAGENOTE_DN_COVER } },
icon: {
emoji: const_1.TableEmoji.success
},
title: [
{
text: {
content: `[${tableName}]`
}
}
],
parent: {
page_id: tableRootPageId
},
properties: notionProperties
})
.then(res => {
this.tables.set(tableName, new Table_1.default({
demoData: demoData,
notion: this.notion,
database_id: res.id,
cloudDescribe: notionProperties,
token: token,
onError: this.onError,
parentPageId: tableRootPageId
}));
return this.tables.get(tableName);
});
});
}
}
exports.default = Database;
//# sourceMappingURL=Database.js.map