@notionhq/client
Version:
A simple and easy to use client for the Notion API
284 lines • 9.54 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.iteratePaginatedAPI = iteratePaginatedAPI;
exports.collectPaginatedAPI = collectPaginatedAPI;
exports.iterateDataSourceTemplates = iterateDataSourceTemplates;
exports.collectDataSourceTemplates = collectDataSourceTemplates;
exports.isFullBlock = isFullBlock;
exports.isFullPage = isFullPage;
exports.isFullDataSource = isFullDataSource;
exports.isFullDatabase = isFullDatabase;
exports.isFullPageOrDataSource = isFullPageOrDataSource;
exports.isFullUser = isFullUser;
exports.isFullComment = isFullComment;
exports.isTextRichTextItemResponse = isTextRichTextItemResponse;
exports.isEquationRichTextItemResponse = isEquationRichTextItemResponse;
exports.isMentionRichTextItemResponse = isMentionRichTextItemResponse;
exports.extractNotionId = extractNotionId;
exports.extractDatabaseId = extractDatabaseId;
exports.extractPageId = extractPageId;
exports.extractBlockId = extractBlockId;
/**
* Returns an async iterator over the results of any paginated Notion API.
*
* Example (given a notion Client called `notion`):
*
* ```
* for await (const block of iteratePaginatedAPI(notion.blocks.children.list, {
* block_id: parentBlockId,
* })) {
* // Do something with block.
* }
* ```
*
* @param listFn A bound function on the Notion client that represents a conforming paginated
* API. Example: `notion.blocks.children.list`.
* @param firstPageArgs Arguments that should be passed to the API on the first and subsequent
* calls to the API. Any necessary `next_cursor` will be automatically populated by
* this function. Example: `{ block_id: "<my block id>" }`
*/
async function* iteratePaginatedAPI(listFn, firstPageArgs) {
let nextCursor = firstPageArgs.start_cursor;
do {
const response = await listFn({
...firstPageArgs,
start_cursor: nextCursor,
});
yield* response.results;
nextCursor = response.next_cursor;
} while (nextCursor);
}
/**
* Collect all of the results of paginating an API into an in-memory array.
*
* Example (given a notion Client called `notion`):
*
* ```
* const blocks = await collectPaginatedAPI(notion.blocks.children.list, {
* block_id: parentBlockId,
* })
* // Do something with blocks.
* ```
*
* @param listFn A bound function on the Notion client that represents a conforming paginated
* API. Example: `notion.blocks.children.list`.
* @param firstPageArgs Arguments that should be passed to the API on the first and subsequent
* calls to the API. Any necessary `next_cursor` will be automatically populated by
* this function. Example: `{ block_id: "<my block id>" }`
*/
async function collectPaginatedAPI(listFn, firstPageArgs) {
const results = [];
for await (const item of iteratePaginatedAPI(listFn, firstPageArgs)) {
results.push(item);
}
return results;
}
/**
* Returns an async iterator over data source templates.
*
* Example (given a notion Client called `notion`):
*
* ```
* for await (const template of iterateDataSourceTemplates(notion, {
* data_source_id: dataSourceId,
* })) {
* console.log(template.name, template.is_default)
* }
* ```
*
* @param client A Notion client instance.
* @param args Arguments including the data_source_id and optional start_cursor.
*/
async function* iterateDataSourceTemplates(client, args) {
let nextCursor = args.start_cursor;
do {
const response = await client.dataSources.listTemplates({
...args,
start_cursor: nextCursor,
});
yield* response.templates;
nextCursor = response.next_cursor;
} while (nextCursor);
}
/**
* Collect all data source templates into an in-memory array.
*
* Example (given a notion Client called `notion`):
*
* ```
* const templates = await collectDataSourceTemplates(notion, {
* data_source_id: dataSourceId,
* })
* // Do something with templates.
* ```
*
* @param client A Notion client instance.
* @param args Arguments including the data_source_id and optional start_cursor.
*/
async function collectDataSourceTemplates(client, args) {
const results = [];
for await (const template of iterateDataSourceTemplates(client, args)) {
results.push(template);
}
return results;
}
/**
* @returns `true` if `response` is a full `BlockObjectResponse`.
*/
function isFullBlock(response) {
return response.object === "block" && "type" in response;
}
/**
* @returns `true` if `response` is a full `PageObjectResponse`.
*/
function isFullPage(response) {
return response.object === "page" && "url" in response;
}
/**
* @returns `true` if `response` is a full `DataSourceObjectResponse`.
*/
function isFullDataSource(response) {
return response.object === "data_source";
}
/**
* @returns `true` if `response` is a full `DatabaseObjectResponse`.
*/
function isFullDatabase(response) {
return response.object === "database";
}
/**
* @returns `true` if `response` is a full `DataSourceObjectResponse` or a full
* `PageObjectResponse`.
*
* Can be used on the results of the list response from `queryDataSource` or
* `search` APIs.
*/
function isFullPageOrDataSource(response) {
if (response.object === "data_source") {
return isFullDataSource(response);
}
else {
return isFullPage(response);
}
}
/**
* @returns `true` if `response` is a full `UserObjectResponse`.
*/
function isFullUser(response) {
return "type" in response;
}
/**
* @returns `true` if `response` is a full `CommentObjectResponse`.
*/
function isFullComment(response) {
return "created_by" in response;
}
/**
* @returns `true` if `richText` is a `TextRichTextItemResponse`.
*/
function isTextRichTextItemResponse(richText) {
return richText.type === "text";
}
/**
* @returns `true` if `richText` is an `EquationRichTextItemResponse`.
*/
function isEquationRichTextItemResponse(richText) {
return richText.type === "equation";
}
/**
* @returns `true` if `richText` is an `MentionRichTextItemResponse`.
*/
function isMentionRichTextItemResponse(richText) {
return richText.type === "mention";
}
/**
* Extracts a Notion ID from a Notion URL or returns the input if it's already a valid ID.
*
* Prioritizes path IDs over query parameters to avoid extracting view IDs instead of database IDs.
*
* @param urlOrId A Notion URL or ID string
* @returns The extracted UUID in standard format (with hyphens) or null if invalid
*
* @example
* ```typescript
* // Database URL with view ID - extracts database ID, not view ID
* extractNotionId('https://notion.so/workspace/DB-abc123def456789012345678901234ab?v=viewid123')
* // Returns: 'abc123de-f456-7890-1234-5678901234ab' (database ID)
*
* // Already formatted UUID
* extractNotionId('12345678-1234-1234-1234-123456789abc')
* // Returns: '12345678-1234-1234-1234-123456789abc'
* ```
*/
function extractNotionId(urlOrId) {
if (!urlOrId || typeof urlOrId !== "string") {
return null;
}
const trimmed = urlOrId.trim();
// Check if it's already a properly formatted UUID
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
if (uuidRegex.test(trimmed)) {
return trimmed.toLowerCase();
}
// Check if it's a compact UUID (32 chars, no hyphens)
const compactUuidRegex = /^[0-9a-f]{32}$/i;
if (compactUuidRegex.test(trimmed)) {
return formatUuid(trimmed);
}
// Extract from URL - prioritize path over query parameters
// This prevents extracting view IDs when database IDs are in the path
const pathMatch = trimmed.match(/\/[^/?#]*-([0-9a-f]{32})(?:[/?#]|$)/i);
if (pathMatch && pathMatch[1]) {
return formatUuid(pathMatch[1]);
}
// Fallback to query parameters if no path ID found
const queryMatch = trimmed.match(/[?&](?:p|page_id|database_id)=([0-9a-f]{32})/i);
if (queryMatch && queryMatch[1]) {
return formatUuid(queryMatch[1]);
}
// Last resort: any 32-char hex string in the URL
const anyMatch = trimmed.match(/([0-9a-f]{32})/i);
if (anyMatch && anyMatch[1]) {
return formatUuid(anyMatch[1]);
}
return null;
}
/**
* Formats a 32-character hex string into a standard UUID format.
* @param compactId 32-character hex string without hyphens
* @returns UUID with hyphens in standard format
*/
function formatUuid(compactId) {
const clean = compactId.toLowerCase();
return `${clean.slice(0, 8)}-${clean.slice(8, 12)}-${clean.slice(12, 16)}-${clean.slice(16, 20)}-${clean.slice(20, 32)}`;
}
/**
* Extracts a database ID from a Notion database URL.
* Convenience wrapper around `extractNotionId`.
*/
function extractDatabaseId(databaseUrl) {
return extractNotionId(databaseUrl);
}
/**
* Extracts a page ID from a Notion page URL.
* Convenience wrapper around `extractNotionId`.
*/
function extractPageId(pageUrl) {
return extractNotionId(pageUrl);
}
/**
* Extracts a block ID from a Notion URL with a block fragment.
* Looks for #block-<id> or #<id> patterns.
*/
function extractBlockId(urlWithBlock) {
if (!urlWithBlock || typeof urlWithBlock !== "string") {
return null;
}
// Look for block fragment in URL (#block-32chars or just #32chars)
const blockMatch = urlWithBlock.match(/#(?:block-)?([0-9a-f]{32})/i);
if (blockMatch && blockMatch[1]) {
return formatUuid(blockMatch[1]);
}
return null;
}
//# sourceMappingURL=helpers.js.map