UNPKG

@pagenote/notion-database

Version:

make notion as a real-database for server

302 lines 13 kB
"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