first commit
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
Security: Sync from Public / sync-from-public (push) Has been cancelled
Test: Benchmark Nightly / build (push) Has been cancelled
Test: Benchmark Nightly / Notify Cats on failure (push) Has been cancelled
CI: Python / Checks (push) Has been cancelled
Test: Evals Python / Workflow Comparison Python (push) Has been cancelled
Util: Check Docs URLs / check-docs-urls (push) Has been cancelled
Test: Visual Storybook / Cloudflare Pages (push) Has been cancelled
Test: E2E Performance / build-and-test-performance (push) Has been cancelled
Test: Workflows Nightly / Run Workflow Tests (push) Has been cancelled
Util: Cleanup CI Docker Images / Delete stale CI images (push) Has been cancelled
Test: Benchmark Destroy Env / build (push) Has been cancelled
Util: Update Node Popularity / update-popularity (push) Has been cancelled
Test: E2E Coverage Weekly / Coverage Tests (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.notion",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Productivity"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/notion/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.notion/"
|
||||
}
|
||||
],
|
||||
"generic": [
|
||||
{
|
||||
"label": "5 tasks you can automate with the new Notion API ",
|
||||
"icon": "⚡️",
|
||||
"url": "https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import type { INodeTypeBaseDescription, IVersionedNodeType } from 'n8n-workflow';
|
||||
import { VersionedNodeType } from 'n8n-workflow';
|
||||
|
||||
import { NotionV1 } from './v1/NotionV1.node';
|
||||
import { NotionV2 } from './v2/NotionV2.node';
|
||||
|
||||
export class Notion extends VersionedNodeType {
|
||||
constructor() {
|
||||
const baseDescription: INodeTypeBaseDescription = {
|
||||
displayName: 'Notion',
|
||||
name: 'notion',
|
||||
icon: { light: 'file:notion.svg', dark: 'file:notion.dark.svg' },
|
||||
group: ['output'],
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume Notion API',
|
||||
defaultVersion: 2.2,
|
||||
};
|
||||
|
||||
const nodeVersions: IVersionedNodeType['nodeVersions'] = {
|
||||
1: new NotionV1(baseDescription),
|
||||
2: new NotionV2(baseDescription),
|
||||
2.1: new NotionV2(baseDescription),
|
||||
2.2: new NotionV2(baseDescription),
|
||||
};
|
||||
|
||||
super(nodeVersions, baseDescription);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"node": "n8n-nodes-base.notionTrigger",
|
||||
"nodeVersion": "1.0",
|
||||
"codexVersion": "1.0",
|
||||
"categories": ["Productivity"],
|
||||
"resources": {
|
||||
"credentialDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/credentials/notion/"
|
||||
}
|
||||
],
|
||||
"primaryDocumentation": [
|
||||
{
|
||||
"url": "https://docs.n8n.io/integrations/builtin/trigger-nodes/n8n-nodes-base.notiontrigger/"
|
||||
}
|
||||
],
|
||||
"generic": [
|
||||
{
|
||||
"label": "5 tasks you can automate with the new Notion API ",
|
||||
"icon": "⚡️",
|
||||
"url": "https://n8n.io/blog/5-tasks-you-can-automate-with-notion-api/"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
import moment from 'moment-timezone';
|
||||
import {
|
||||
type IPollFunctions,
|
||||
type IDataObject,
|
||||
type INodeExecutionData,
|
||||
type INodeType,
|
||||
type INodeTypeDescription,
|
||||
NodeConnectionTypes,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
databaseUrlExtractionRegexp,
|
||||
databaseUrlValidationRegexp,
|
||||
idExtractionRegexp,
|
||||
idValidationRegexp,
|
||||
} from './shared/constants';
|
||||
import { notionApiRequest, simplifyObjects } from './shared/GenericFunctions';
|
||||
import { listSearch } from './shared/methods';
|
||||
|
||||
export class NotionTrigger implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Notion Trigger',
|
||||
name: 'notionTrigger',
|
||||
icon: { light: 'file:notion.svg', dark: 'file:notion.dark.svg' },
|
||||
group: ['trigger'],
|
||||
version: 1,
|
||||
description: 'Starts the workflow when Notion events occur',
|
||||
subtitle: '={{$parameter["event"]}}',
|
||||
defaults: {
|
||||
name: 'Notion Trigger',
|
||||
},
|
||||
credentials: [
|
||||
{
|
||||
name: 'notionApi',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
polling: true,
|
||||
inputs: [],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
properties: [
|
||||
{
|
||||
displayName: 'Event',
|
||||
name: 'event',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Page Added to Database',
|
||||
value: 'pageAddedToDatabase',
|
||||
},
|
||||
{
|
||||
name: 'Page Updated in Database',
|
||||
value: 'pagedUpdatedInDatabase',
|
||||
},
|
||||
],
|
||||
required: true,
|
||||
default: 'pageAddedToDatabase',
|
||||
},
|
||||
{
|
||||
displayName:
|
||||
'In Notion, make sure to <a href="https://www.notion.so/help/add-and-manage-connections-with-the-api" target="_blank">add your connection</a> to the pages you want to access.',
|
||||
name: 'notionNotice',
|
||||
type: 'notice',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Database',
|
||||
name: 'databaseId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'list', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Database',
|
||||
name: 'list',
|
||||
type: 'list',
|
||||
placeholder: 'Select a Database...',
|
||||
typeOptions: {
|
||||
searchListMethod: 'getDatabases',
|
||||
searchable: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder:
|
||||
'https://www.notion.so/0fe2f7de558b471eab07e9d871cdf4a9?v=f2d424ba0c404733a3f500c78c881610',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: databaseUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: databaseUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
event: ['pageAddedToDatabase', 'pagedUpdatedInDatabase'],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Database to operate on',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
event: ['pageAddedToDatabase', 'pagedUpdatedInDatabase'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description:
|
||||
'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
methods = {
|
||||
listSearch,
|
||||
};
|
||||
|
||||
async poll(this: IPollFunctions): Promise<INodeExecutionData[][] | null> {
|
||||
const webhookData = this.getWorkflowStaticData('node');
|
||||
const databaseId = this.getNodeParameter('databaseId', '', { extractValue: true }) as string;
|
||||
const event = this.getNodeParameter('event') as string;
|
||||
const simple = this.getNodeParameter('simple') as boolean;
|
||||
|
||||
const lastTimeChecked = webhookData.lastTimeChecked
|
||||
? moment(webhookData.lastTimeChecked as string)
|
||||
: moment().set({ second: 0, millisecond: 0 }); // Notion timestamp accuracy is only down to the minute
|
||||
|
||||
// update lastTimeChecked to now
|
||||
webhookData.lastTimeChecked = moment().set({ second: 0, millisecond: 0 });
|
||||
|
||||
// because Notion timestamp accuracy is only down to the minute some duplicates can be fetch
|
||||
const possibleDuplicates = (webhookData.possibleDuplicates as string[]) ?? [];
|
||||
|
||||
const sortProperty = event === 'pageAddedToDatabase' ? 'created_time' : 'last_edited_time';
|
||||
|
||||
const option: IDataObject = {
|
||||
headers: {
|
||||
'Notion-Version': '2022-02-22',
|
||||
},
|
||||
};
|
||||
|
||||
const body: IDataObject = {
|
||||
page_size: 1,
|
||||
sorts: [
|
||||
{
|
||||
timestamp: sortProperty,
|
||||
direction: 'descending',
|
||||
},
|
||||
],
|
||||
...(this.getMode() !== 'manual' && {
|
||||
filter: {
|
||||
timestamp: sortProperty,
|
||||
[sortProperty]: {
|
||||
on_or_after: lastTimeChecked.utc().format(),
|
||||
},
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
let records: IDataObject[] = [];
|
||||
|
||||
let hasMore = true;
|
||||
|
||||
//get last record
|
||||
let { results: data } = await notionApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
`/databases/${databaseId}/query`,
|
||||
body,
|
||||
{},
|
||||
'',
|
||||
option,
|
||||
);
|
||||
|
||||
if (this.getMode() === 'manual') {
|
||||
if (simple) {
|
||||
data = simplifyObjects(data, false, 1);
|
||||
}
|
||||
if (Array.isArray(data) && data.length) {
|
||||
return [this.helpers.returnJsonArray(data)];
|
||||
}
|
||||
}
|
||||
|
||||
// if something changed after the last check
|
||||
if (Array.isArray(data) && data.length && Object.keys(data[0] as IDataObject).length !== 0) {
|
||||
do {
|
||||
body.page_size = 10;
|
||||
const { results, has_more, next_cursor } = await notionApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
`/databases/${databaseId}/query`,
|
||||
body,
|
||||
{},
|
||||
'',
|
||||
option,
|
||||
);
|
||||
records.push(...(results as IDataObject[]));
|
||||
hasMore = has_more;
|
||||
if (next_cursor !== null) {
|
||||
body.start_cursor = next_cursor;
|
||||
}
|
||||
// Only stop when we reach records strictly before last recorded time to be sure we catch records from the same minute
|
||||
} while (
|
||||
!moment(records[records.length - 1][sortProperty] as string).isBefore(lastTimeChecked) &&
|
||||
hasMore
|
||||
);
|
||||
|
||||
// Filter out already processed left over records:
|
||||
// with a time strictly before the last record processed
|
||||
// or from the same minute not present in the list of processed records
|
||||
records = records.filter(
|
||||
(record: IDataObject) => !possibleDuplicates.includes(record.id as string),
|
||||
);
|
||||
|
||||
// Save the time of the most recent record processed
|
||||
if (records[0]) {
|
||||
const latestTimestamp = moment(records[0][sortProperty] as string);
|
||||
|
||||
// Save record ids with the same timestamp as the latest processed records
|
||||
webhookData.possibleDuplicates = records
|
||||
.filter((record: IDataObject) =>
|
||||
moment(record[sortProperty] as string).isSame(latestTimestamp),
|
||||
)
|
||||
.map((record: IDataObject) => record.id);
|
||||
} else {
|
||||
webhookData.possibleDuplicates = undefined;
|
||||
}
|
||||
|
||||
if (simple) {
|
||||
records = simplifyObjects(records, false, 1);
|
||||
}
|
||||
|
||||
if (Array.isArray(records) && records.length) {
|
||||
return [this.helpers.returnJsonArray(records)];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"Messaggi Schedulati": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 2
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"has_more": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"next_cursor": {
|
||||
"type": "null"
|
||||
},
|
||||
"object": {
|
||||
"type": "string"
|
||||
},
|
||||
"request_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"results": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"archived": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"created_by": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"object": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"created_time": {
|
||||
"type": "string"
|
||||
},
|
||||
"has_children": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"in_trash": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"object": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"last_edited_time": {
|
||||
"type": "string"
|
||||
},
|
||||
"object": {
|
||||
"type": "string"
|
||||
},
|
||||
"paragraph": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bold": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"code": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"italic": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"strikethrough": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"underline": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"plain_text": {
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"parent": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"page_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": 2
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"archived": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"has_children": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"in_trash": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"object": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"object": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"page_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parent_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"root_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"archived": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"created_by": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"object": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"created_time": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bold": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"code": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"italic": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"strikethrough": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"underline": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"href": {
|
||||
"type": "null"
|
||||
},
|
||||
"plain_text": {
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"link": {
|
||||
"type": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"in_trash": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"is_inline": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"object": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"last_edited_time": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"object": {
|
||||
"type": "string"
|
||||
},
|
||||
"parent": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"page_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"workspace": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"answer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Author": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Dateien und Medien": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"department": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"multi_select": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Name": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Produkt-ID": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"number": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"format": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"question": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Tag": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"multi_select": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"multi_select": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"options": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"updated_at": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Zuletzt aktualisiert": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"description": {
|
||||
"type": "null"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"public_url": {
|
||||
"type": "null"
|
||||
},
|
||||
"request_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"title": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bold": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"code": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"color": {
|
||||
"type": "string"
|
||||
},
|
||||
"italic": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"strikethrough": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"underline": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"href": {
|
||||
"type": "null"
|
||||
},
|
||||
"plain_text": {
|
||||
"type": "string"
|
||||
},
|
||||
"text": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "string"
|
||||
},
|
||||
"link": {
|
||||
"type": "null"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 6
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 2
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 2
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"object": {
|
||||
"type": "string"
|
||||
},
|
||||
"person": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"request_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"object": {
|
||||
"type": "string"
|
||||
},
|
||||
"person": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"version": 1
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.58276 6.97679C8.82047 7.98238 9.28479 7.90566 11.6091 7.75057L33.5206 6.43488C33.9853 6.43488 33.5989 5.97127 33.4439 5.89423L29.8049 3.26348C29.1076 2.72213 28.1786 2.10217 26.3982 2.25726L5.18115 3.80476C4.40736 3.88148 4.25282 4.26837 4.56096 4.57847L7.58276 6.97679ZM8.89829 12.0833V35.1381C8.89829 36.3771 9.51746 36.8407 10.911 36.764L34.9919 35.3706C36.3862 35.2939 36.5415 34.4417 36.5415 33.4352V10.5351C36.5415 9.53019 36.1549 8.98829 35.3014 9.06564L10.1367 10.5351C9.20799 10.6131 8.89821 11.0777 8.89821 12.0833H8.89829ZM32.6708 13.32C32.8252 14.017 32.6708 14.7133 31.9725 14.7917L30.8123 15.0229V32.0434C29.8049 32.5848 28.8759 32.8944 28.1018 32.8944C26.8625 32.8944 26.5521 32.5072 25.6237 31.3474L18.0343 19.4329V30.9605L20.4359 31.5024C20.4359 31.5024 20.4359 32.8944 18.4983 32.8944L13.1568 33.2042C13.0016 32.8944 13.1568 32.1214 13.6986 31.9665L15.0925 31.5802V16.3385L13.1572 16.1834C13.0019 15.4864 13.3885 14.4814 14.4733 14.4035L20.2035 14.0172L28.1018 26.0868V15.4097L26.0881 15.1786C25.9335 14.3265 26.5521 13.7078 27.3265 13.6311L32.6708 13.32ZM3.39973 1.71598L25.4688 0.0907457C28.179 -0.141688 28.8763 0.0140245 30.5796 1.25135L37.6243 6.20276C38.7867 7.05421 39.1742 7.28602 39.1742 8.21419V35.3706C39.1742 37.0726 38.5542 38.0791 36.3865 38.2331L10.7577 39.7807C9.13049 39.8583 8.35607 39.6264 7.50392 38.5426L2.31608 31.8117C1.38658 30.5726 1 29.6457 1 28.5613V4.42283C1 3.03105 1.62019 1.87005 3.39973 1.71598V1.71598Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.58276 6.97679C8.82047 7.98238 9.28479 7.90566 11.6091 7.75057L33.5206 6.43488C33.9853 6.43488 33.5989 5.97127 33.4439 5.89423L29.8049 3.26348C29.1076 2.72213 28.1786 2.10217 26.3982 2.25726L5.18115 3.80476C4.40736 3.88148 4.25282 4.26837 4.56096 4.57847L7.58276 6.97679ZM8.89829 12.0833V35.1381C8.89829 36.3771 9.51746 36.8407 10.911 36.764L34.9919 35.3706C36.3862 35.2939 36.5415 34.4417 36.5415 33.4352V10.5351C36.5415 9.53019 36.1549 8.98829 35.3014 9.06564L10.1367 10.5351C9.20799 10.6131 8.89821 11.0777 8.89821 12.0833H8.89829ZM32.6708 13.32C32.8252 14.017 32.6708 14.7133 31.9725 14.7917L30.8123 15.0229V32.0434C29.8049 32.5848 28.8759 32.8944 28.1018 32.8944C26.8625 32.8944 26.5521 32.5072 25.6237 31.3474L18.0343 19.4329V30.9605L20.4359 31.5024C20.4359 31.5024 20.4359 32.8944 18.4983 32.8944L13.1568 33.2042C13.0016 32.8944 13.1568 32.1214 13.6986 31.9665L15.0925 31.5802V16.3385L13.1572 16.1834C13.0019 15.4864 13.3885 14.4814 14.4733 14.4035L20.2035 14.0172L28.1018 26.0868V15.4097L26.0881 15.1786C25.9335 14.3265 26.5521 13.7078 27.3265 13.6311L32.6708 13.32ZM3.39973 1.71598L25.4688 0.0907457C28.179 -0.141688 28.8763 0.0140245 30.5796 1.25135L37.6243 6.20276C38.7867 7.05421 39.1742 7.28602 39.1742 8.21419V35.3706C39.1742 37.0726 38.5542 38.0791 36.3865 38.2331L10.7577 39.7807C9.13049 39.8583 8.35607 39.6264 7.50392 38.5426L2.31608 31.8117C1.38658 30.5726 1 29.6457 1 28.5613V4.42283C1 3.03105 1.62019 1.87005 3.39973 1.71598V1.71598Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
const notionIdRegexp = '[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}';
|
||||
|
||||
export const idExtractionRegexp = `^(${notionIdRegexp})`;
|
||||
export const idValidationRegexp = `${idExtractionRegexp}.*`;
|
||||
|
||||
const baseUrlRegexp = '(?:https|http)://www\\.notion\\.so/(?:[a-z0-9-]{2,}/)?';
|
||||
|
||||
export const databaseUrlExtractionRegexp = `${baseUrlRegexp}(${notionIdRegexp})`;
|
||||
export const databaseUrlValidationRegexp = `${databaseUrlExtractionRegexp}.*`;
|
||||
|
||||
export const databasePageUrlExtractionRegexp = `${baseUrlRegexp}(?:[a-zA-Z0-9-]{1,}-)?(${notionIdRegexp})`;
|
||||
export const databasePageUrlValidationRegexp = `${databasePageUrlExtractionRegexp}.*`;
|
||||
|
||||
export const blockUrlExtractionRegexp = `${baseUrlRegexp}(?:[a-zA-Z0-9-]{2,}-)?(${notionIdRegexp})`;
|
||||
export const blockUrlValidationRegexp = `${blockUrlExtractionRegexp}.*`;
|
||||
@@ -0,0 +1,291 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { blocks } from './Blocks';
|
||||
import {
|
||||
blockUrlExtractionRegexp,
|
||||
blockUrlValidationRegexp,
|
||||
idExtractionRegexp,
|
||||
idValidationRegexp,
|
||||
} from '../constants';
|
||||
|
||||
//RLC with fixed regex for blockId
|
||||
const blockIdRLC: INodeProperties = {
|
||||
displayName: 'Block',
|
||||
name: 'blockId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder:
|
||||
'e.g. https://www.notion.so/Block-Test-88888ccc303e4f44847f27d24bd7ad8e?pvs=4#c44444444444bbbbb4d32fdfdd84e',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: blockUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
// extractValue: {
|
||||
// type: 'regex',
|
||||
// regex: blockUrlExtractionRegexp,
|
||||
// },
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'e.g. ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
description:
|
||||
"The Notion Block to get all children from, when using 'By URL' mode make sure to use the URL of the block itself, you can find it in block parameters in Notion under 'Copy link to block'",
|
||||
};
|
||||
|
||||
export const blockOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Append After',
|
||||
value: 'append',
|
||||
description: 'Append a block',
|
||||
action: 'Append a block',
|
||||
},
|
||||
{
|
||||
// eslint-disable-next-line n8n-nodes-base/node-param-option-name-wrong-for-get-many
|
||||
name: 'Get Child Blocks',
|
||||
value: 'getAll',
|
||||
description: 'Get many child blocks',
|
||||
action: 'Get many child blocks',
|
||||
},
|
||||
],
|
||||
default: 'append',
|
||||
},
|
||||
];
|
||||
|
||||
export const blockFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* block:append */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Block',
|
||||
name: 'blockId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder: 'https://www.notion.so/My-Page-b4eeb113e118403ba450af65ac25f0b9',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: blockUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: blockUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['append'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [{ _cnd: { gte: 2.2 } }],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Block to append blocks to',
|
||||
},
|
||||
{
|
||||
...blockIdRLC,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['append'],
|
||||
'@version': [{ _cnd: { gte: 2.2 } }],
|
||||
},
|
||||
},
|
||||
},
|
||||
...blocks('block', 'append'),
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* block:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Block',
|
||||
name: 'blockId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder: 'https://www.notion.so/My-Page-b4eeb113e118403ba450af65ac25f0b9',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: blockUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: blockUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Block ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [{ _cnd: { gte: 2.2 } }],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Block to get all children from',
|
||||
},
|
||||
{
|
||||
...blockIdRLC,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
'@version': [{ _cnd: { gte: 2.2 } }],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Also Fetch Nested Blocks',
|
||||
name: 'fetchNestedBlocks',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify Output',
|
||||
name: 'simplifyOutput',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['block'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1, 2],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,603 @@
|
||||
import type { IDisplayOptions, INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
databaseUrlExtractionRegexp,
|
||||
databaseUrlValidationRegexp,
|
||||
idExtractionRegexp,
|
||||
idValidationRegexp,
|
||||
} from '../constants';
|
||||
|
||||
const colors = [
|
||||
{
|
||||
name: 'Default',
|
||||
value: 'default',
|
||||
},
|
||||
{
|
||||
name: 'Gray',
|
||||
value: 'gray',
|
||||
},
|
||||
{
|
||||
name: 'Brown',
|
||||
value: 'brown',
|
||||
},
|
||||
{
|
||||
name: 'Orange',
|
||||
value: 'orange',
|
||||
},
|
||||
{
|
||||
name: 'Yellow',
|
||||
value: 'yellow',
|
||||
},
|
||||
{
|
||||
name: 'Green',
|
||||
value: 'green',
|
||||
},
|
||||
{
|
||||
name: 'Blue',
|
||||
value: 'blue',
|
||||
},
|
||||
{
|
||||
name: 'Purple',
|
||||
value: 'purple',
|
||||
},
|
||||
{
|
||||
name: 'Pink',
|
||||
value: 'pink',
|
||||
},
|
||||
{
|
||||
name: 'Red',
|
||||
value: 'red',
|
||||
},
|
||||
{
|
||||
name: 'Gray Background',
|
||||
value: 'gray_background',
|
||||
},
|
||||
{
|
||||
name: 'Brown Background',
|
||||
value: 'brown_background',
|
||||
},
|
||||
{
|
||||
name: 'Orange Background',
|
||||
value: 'orange_background',
|
||||
},
|
||||
{
|
||||
name: 'Yellow Background',
|
||||
value: 'yellow_background',
|
||||
},
|
||||
{
|
||||
name: 'Green Background',
|
||||
value: 'green_background',
|
||||
},
|
||||
{
|
||||
name: 'Blue Background',
|
||||
value: 'blue_background',
|
||||
},
|
||||
{
|
||||
name: 'Purple Background',
|
||||
value: 'purple_background',
|
||||
},
|
||||
{
|
||||
name: 'Pink Background',
|
||||
value: 'pink_background',
|
||||
},
|
||||
{
|
||||
name: 'Red Background',
|
||||
value: 'red_background',
|
||||
},
|
||||
];
|
||||
|
||||
const annotation: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Annotations',
|
||||
name: 'annotationUi',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Annotation',
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Bold',
|
||||
name: 'bold',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the text is bolded',
|
||||
},
|
||||
{
|
||||
displayName: 'Italic',
|
||||
name: 'italic',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the text is italicized',
|
||||
},
|
||||
{
|
||||
displayName: 'Strikethrough',
|
||||
name: 'strikethrough',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the text is struck through',
|
||||
},
|
||||
{
|
||||
displayName: 'Underline',
|
||||
name: 'underline',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the text is underlined',
|
||||
},
|
||||
{
|
||||
displayName: 'Code',
|
||||
name: 'code',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether the text is code style',
|
||||
},
|
||||
{
|
||||
displayName: 'Color',
|
||||
name: 'color',
|
||||
type: 'options',
|
||||
options: colors,
|
||||
default: '',
|
||||
description: 'Color of the text',
|
||||
},
|
||||
],
|
||||
description: 'All annotations that apply to this rich text',
|
||||
},
|
||||
];
|
||||
|
||||
const typeMention: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'mentionType',
|
||||
type: 'options',
|
||||
displayOptions: {
|
||||
show: {
|
||||
textType: ['mention'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Database',
|
||||
value: 'database',
|
||||
},
|
||||
{
|
||||
name: 'Date',
|
||||
value: 'date',
|
||||
},
|
||||
{
|
||||
name: 'Page',
|
||||
value: 'page',
|
||||
},
|
||||
{
|
||||
name: 'User',
|
||||
value: 'user',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
description:
|
||||
'An inline mention of a user, page, database, or date. In the app these are created by typing @ followed by the name of a user, page, database, or a date.',
|
||||
},
|
||||
{
|
||||
displayName: 'User Name or ID',
|
||||
name: 'user',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getUsers',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['user'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'The ID of the user being mentioned. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Page ID',
|
||||
name: 'page',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['page'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'The ID of the page being mentioned',
|
||||
},
|
||||
{
|
||||
displayName: 'Database',
|
||||
name: 'database',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'list', value: '' },
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Database',
|
||||
name: 'list',
|
||||
type: 'list',
|
||||
placeholder: 'Select a Database...',
|
||||
typeOptions: {
|
||||
searchListMethod: 'getDatabases',
|
||||
searchable: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder:
|
||||
'https://www.notion.so/0fe2f7de558b471eab07e9d871cdf4a9?v=f2d424ba0c404733a3f500c78c881610',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: databaseUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: databaseUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['database'],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Database being mentioned',
|
||||
},
|
||||
{
|
||||
displayName: 'Range',
|
||||
name: 'range',
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['date'],
|
||||
},
|
||||
},
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description: 'Whether or not you want to define a date range',
|
||||
},
|
||||
{
|
||||
displayName: 'Date',
|
||||
name: 'date',
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['date'],
|
||||
range: [false],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
{
|
||||
displayName: 'Date Start',
|
||||
name: 'dateStart',
|
||||
displayOptions: {
|
||||
show: {
|
||||
mentionType: ['date'],
|
||||
range: [true],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
{
|
||||
displayName: 'Date End',
|
||||
name: 'dateEnd',
|
||||
displayOptions: {
|
||||
show: {
|
||||
range: [true],
|
||||
mentionType: ['date'],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description:
|
||||
'An ISO 8601 formatted date, with optional time. Represents the end of a date range.',
|
||||
},
|
||||
];
|
||||
|
||||
const typeEquation: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Expression',
|
||||
name: 'expression',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
textType: ['equation'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
];
|
||||
|
||||
const typeText: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'text',
|
||||
displayOptions: {
|
||||
show: {
|
||||
textType: ['text'],
|
||||
},
|
||||
},
|
||||
type: 'string',
|
||||
default: '',
|
||||
description:
|
||||
"Text content. This field contains the actual content of your text and is probably the field you'll use most often.",
|
||||
},
|
||||
{
|
||||
displayName: 'Is Link',
|
||||
name: 'isLink',
|
||||
displayOptions: {
|
||||
show: {
|
||||
textType: ['text'],
|
||||
},
|
||||
},
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
},
|
||||
{
|
||||
displayName: 'Text Link',
|
||||
name: 'textLink',
|
||||
displayOptions: {
|
||||
show: {
|
||||
textType: ['text'],
|
||||
isLink: [true],
|
||||
},
|
||||
},
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'The URL that this link points to',
|
||||
},
|
||||
];
|
||||
|
||||
export const text = (displayOptions: IDisplayOptions): INodeProperties[] =>
|
||||
[
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'text',
|
||||
placeholder: 'Add Text',
|
||||
type: 'fixedCollection',
|
||||
default: {},
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
displayOptions,
|
||||
options: [
|
||||
{
|
||||
name: 'text',
|
||||
displayName: 'Text',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'textType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Equation',
|
||||
value: 'equation',
|
||||
},
|
||||
{
|
||||
name: 'Mention',
|
||||
value: 'mention',
|
||||
},
|
||||
{
|
||||
name: 'Text',
|
||||
value: 'text',
|
||||
},
|
||||
],
|
||||
default: 'text',
|
||||
},
|
||||
...typeText,
|
||||
...typeMention,
|
||||
...typeEquation,
|
||||
|
||||
...annotation,
|
||||
],
|
||||
},
|
||||
],
|
||||
description: 'Rich text in the block',
|
||||
},
|
||||
] as INodeProperties[];
|
||||
|
||||
const todo = (type: string): INodeProperties[] =>
|
||||
[
|
||||
{
|
||||
displayName: 'Checked',
|
||||
name: 'checked',
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [type],
|
||||
},
|
||||
},
|
||||
description: 'Whether the to_do is checked or not',
|
||||
},
|
||||
] as INodeProperties[];
|
||||
|
||||
const title = (type: string): INodeProperties[] =>
|
||||
[
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [type],
|
||||
},
|
||||
},
|
||||
description: 'Plain text of page title',
|
||||
},
|
||||
] as INodeProperties[];
|
||||
|
||||
const richText = (displayOptions: IDisplayOptions): INodeProperties[] => [
|
||||
{
|
||||
displayName: 'Rich Text',
|
||||
name: 'richText',
|
||||
type: 'boolean',
|
||||
displayOptions,
|
||||
default: false,
|
||||
},
|
||||
];
|
||||
|
||||
const textContent = (displayOptions: IDisplayOptions): INodeProperties[] => [
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'textContent',
|
||||
type: 'string',
|
||||
displayOptions,
|
||||
default: '',
|
||||
},
|
||||
];
|
||||
|
||||
const imageBlock = (type: string): INodeProperties[] => [
|
||||
{
|
||||
displayName: 'Image URL',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: [type],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Image file reference',
|
||||
},
|
||||
];
|
||||
|
||||
const block = (blockType: string): INodeProperties[] => {
|
||||
const data: INodeProperties[] = [];
|
||||
switch (blockType) {
|
||||
case 'to_do':
|
||||
data.push(...todo(blockType));
|
||||
data.push(
|
||||
...richText({
|
||||
show: {
|
||||
type: [blockType],
|
||||
},
|
||||
}),
|
||||
);
|
||||
data.push(
|
||||
...textContent({
|
||||
show: {
|
||||
type: [blockType],
|
||||
richText: [false],
|
||||
},
|
||||
}),
|
||||
);
|
||||
data.push(
|
||||
...text({
|
||||
show: {
|
||||
type: [blockType],
|
||||
richText: [true],
|
||||
},
|
||||
}),
|
||||
);
|
||||
break;
|
||||
case 'child_page':
|
||||
data.push(...title(blockType));
|
||||
break;
|
||||
case 'image':
|
||||
data.push(...imageBlock(blockType));
|
||||
break;
|
||||
default:
|
||||
data.push(
|
||||
...richText({
|
||||
show: {
|
||||
type: [blockType],
|
||||
},
|
||||
}),
|
||||
);
|
||||
data.push(
|
||||
...textContent({
|
||||
show: {
|
||||
type: [blockType],
|
||||
richText: [false],
|
||||
},
|
||||
}),
|
||||
);
|
||||
data.push(
|
||||
...text({
|
||||
show: {
|
||||
type: [blockType],
|
||||
richText: [true],
|
||||
},
|
||||
}),
|
||||
);
|
||||
break;
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
export const blocks = (resource: string, operation: string): INodeProperties[] => [
|
||||
{
|
||||
displayName: 'Blocks',
|
||||
name: 'blockUi',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [resource],
|
||||
operation: [operation],
|
||||
},
|
||||
},
|
||||
placeholder: 'Add Block',
|
||||
options: [
|
||||
{
|
||||
name: 'blockValues',
|
||||
displayName: 'Block',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Type Name or ID',
|
||||
name: 'type',
|
||||
type: 'options',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getBlockTypes',
|
||||
},
|
||||
default: 'paragraph',
|
||||
},
|
||||
...block('paragraph'),
|
||||
...block('heading_1'),
|
||||
...block('heading_2'),
|
||||
...block('heading_3'),
|
||||
...block('toggle'),
|
||||
...block('to_do'),
|
||||
...block('child_page'),
|
||||
...block('bulleted_list_item'),
|
||||
...block('numbered_list_item'),
|
||||
...block('image'),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,320 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
databaseUrlExtractionRegexp,
|
||||
databaseUrlValidationRegexp,
|
||||
idExtractionRegexp,
|
||||
idValidationRegexp,
|
||||
} from '../constants';
|
||||
|
||||
export const databaseOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a database',
|
||||
action: 'Get a database',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many databases',
|
||||
action: 'Get many databases',
|
||||
},
|
||||
{
|
||||
name: 'Search',
|
||||
value: 'search',
|
||||
description: 'Search databases using text search',
|
||||
action: 'Search a database',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [1],
|
||||
resource: ['database'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a database',
|
||||
action: 'Get a database',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many databases',
|
||||
action: 'Get many databases',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const databaseFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* database:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
{
|
||||
displayName: 'Database',
|
||||
name: 'databaseId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'list', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Database',
|
||||
name: 'list',
|
||||
type: 'list',
|
||||
placeholder: 'Select a Database...',
|
||||
typeOptions: {
|
||||
searchListMethod: 'getDatabases',
|
||||
searchable: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder:
|
||||
'https://www.notion.so/0fe2f7de558b471eab07e9d871cdf4a9?v=f2d424ba0c404733a3f500c78c881610',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: databaseUrlValidationRegexp,
|
||||
errorMessage:
|
||||
'Not a valid Notion Database URL. Hint: use the URL of the database itself, not a page containing it.',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: databaseUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Database to get',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* database:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['getAll', 'get'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* database:search */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Search Text',
|
||||
name: 'text',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
description: 'The text to search for',
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['search'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['database'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sort',
|
||||
placeholder: 'Add Sort',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: false,
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sortValue',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Direction',
|
||||
name: 'direction',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Ascending',
|
||||
value: 'ascending',
|
||||
},
|
||||
{
|
||||
name: 'Descending',
|
||||
value: 'descending',
|
||||
},
|
||||
],
|
||||
default: 'descending',
|
||||
description: 'The direction to sort',
|
||||
},
|
||||
{
|
||||
displayName: 'Timestamp',
|
||||
name: 'timestamp',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Last Edited Time',
|
||||
value: 'last_edited_time',
|
||||
},
|
||||
],
|
||||
default: 'last_edited_time',
|
||||
description: 'The name of the timestamp to sort against',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,388 @@
|
||||
export const filters = (conditions: any) => [
|
||||
{
|
||||
displayName: 'Property Name or ID',
|
||||
name: 'key',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getFilterProperties',
|
||||
loadOptionsDependsOn: ['datatabaseId'],
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'The name of the property to filter by. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Type',
|
||||
name: 'type',
|
||||
type: 'hidden',
|
||||
default: '={{$parameter["&key"].split("|")[1]}}',
|
||||
},
|
||||
...conditions,
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'titleValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['title'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'richTextValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['rich_text'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Phone Number',
|
||||
name: 'phoneNumberValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['phone_number'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: 'Phone number. No structure is enforced.',
|
||||
},
|
||||
{
|
||||
displayName: 'Option Name or ID',
|
||||
name: 'multiSelectValue',
|
||||
type: 'options',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getPropertySelectValues',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['multi_select'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: [],
|
||||
},
|
||||
{
|
||||
displayName: 'Option Name or ID',
|
||||
name: 'selectValue',
|
||||
type: 'options',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getPropertySelectValues',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['select'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Status Name or ID',
|
||||
name: 'statusValue',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getPropertySelectValues',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['status'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>',
|
||||
},
|
||||
{
|
||||
displayName: 'Email',
|
||||
name: 'emailValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['email'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'URL',
|
||||
name: 'urlValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['url'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'User Name or ID',
|
||||
name: 'peopleValue',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getUsers',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['people'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'List of users. Multiples can be defined separated by comma. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'User Name or ID',
|
||||
name: 'createdByValue',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getUsers',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['created_by'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'List of users. Multiples can be defined separated by comma. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'User Name or ID',
|
||||
name: 'lastEditedByValue',
|
||||
type: 'options',
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getUsers',
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['last_edited_by'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description:
|
||||
'List of users. Multiples can be defined separated by comma. Choose from the list, or specify an ID using an <a href="https://docs.n8n.io/code/expressions/">expression</a>.',
|
||||
},
|
||||
{
|
||||
displayName: 'Relation ID',
|
||||
name: 'relationValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['relation'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Checked',
|
||||
name: 'checkboxValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['checkbox'],
|
||||
},
|
||||
},
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
'Whether or not the checkbox is checked. <code>true</code> represents checked. <code>false</code> represents unchecked',
|
||||
},
|
||||
{
|
||||
displayName: 'Number',
|
||||
name: 'numberValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['number'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'Number value',
|
||||
},
|
||||
{
|
||||
displayName: 'Date',
|
||||
name: 'date',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['date'],
|
||||
},
|
||||
hide: {
|
||||
condition: [
|
||||
'is_empty',
|
||||
'is_not_empty',
|
||||
'past_week',
|
||||
'past_month',
|
||||
'past_year',
|
||||
'next_week',
|
||||
'next_month',
|
||||
'next_year',
|
||||
],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
{
|
||||
displayName: 'Created Time',
|
||||
name: 'createdTimeValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['created_time'],
|
||||
},
|
||||
hide: {
|
||||
condition: [
|
||||
'is_empty',
|
||||
'is_not_empty',
|
||||
'past_week',
|
||||
'past_month',
|
||||
'past_year',
|
||||
'next_week',
|
||||
'next_month',
|
||||
'next_year',
|
||||
],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
{
|
||||
displayName: 'Last Edited Time',
|
||||
name: 'lastEditedTime',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['last_edited_time'],
|
||||
},
|
||||
hide: {
|
||||
condition: [
|
||||
'is_empty',
|
||||
'is_not_empty',
|
||||
'past_week',
|
||||
'past_month',
|
||||
'past_year',
|
||||
'next_week',
|
||||
'next_month',
|
||||
'next_year',
|
||||
],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
//formula types
|
||||
{
|
||||
displayName: 'Number',
|
||||
name: 'numberValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['formula'],
|
||||
returnType: ['number'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
type: 'number',
|
||||
default: 0,
|
||||
description: 'Number value',
|
||||
},
|
||||
{
|
||||
displayName: 'Text',
|
||||
name: 'textValue',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['formula'],
|
||||
returnType: ['text'],
|
||||
},
|
||||
hide: {
|
||||
condition: ['is_empty', 'is_not_empty'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Boolean',
|
||||
name: 'checkboxValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['formula'],
|
||||
returnType: ['checkbox'],
|
||||
},
|
||||
},
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
description:
|
||||
'Whether or not the checkbox is checked. <code>true</code> represents checked. <code>false</code> represents unchecked',
|
||||
},
|
||||
{
|
||||
displayName: 'Date',
|
||||
name: 'dateValue',
|
||||
displayOptions: {
|
||||
show: {
|
||||
type: ['formula'],
|
||||
returnType: ['date'],
|
||||
},
|
||||
hide: {
|
||||
condition: [
|
||||
'is_empty',
|
||||
'is_not_empty',
|
||||
'past_week',
|
||||
'past_month',
|
||||
'past_year',
|
||||
'next_week',
|
||||
'next_month',
|
||||
'next_year',
|
||||
],
|
||||
},
|
||||
},
|
||||
type: 'dateTime',
|
||||
default: '',
|
||||
description: 'An ISO 8601 format date, with optional time',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,491 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
import { blocks } from './Blocks';
|
||||
import {
|
||||
databasePageUrlExtractionRegexp,
|
||||
databasePageUrlValidationRegexp,
|
||||
idExtractionRegexp,
|
||||
idValidationRegexp,
|
||||
} from '../constants';
|
||||
|
||||
export const pageOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [1],
|
||||
resource: ['page'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a page',
|
||||
action: 'Create a page',
|
||||
},
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a page',
|
||||
action: 'Get a page',
|
||||
},
|
||||
{
|
||||
name: 'Search',
|
||||
value: 'search',
|
||||
description: 'Text search of pages',
|
||||
action: 'Search a page',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Archive',
|
||||
value: 'archive',
|
||||
description: 'Archive a page',
|
||||
action: 'Archive a page',
|
||||
},
|
||||
{
|
||||
name: 'Create',
|
||||
value: 'create',
|
||||
description: 'Create a page',
|
||||
action: 'Create a page',
|
||||
},
|
||||
{
|
||||
name: 'Search',
|
||||
value: 'search',
|
||||
description: 'Text search of pages',
|
||||
action: 'Search a page',
|
||||
},
|
||||
],
|
||||
default: 'create',
|
||||
},
|
||||
];
|
||||
|
||||
export const pageFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* page:archive */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Page',
|
||||
name: 'pageId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder: 'https://www.notion.so/My-Page-b4eeb113e118403aa450af65ac25f0b9',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: databasePageUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database Page URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: databasePageUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Page ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['archive'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Page to archive',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['archive'],
|
||||
},
|
||||
hide: {
|
||||
'@version': [1],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* page:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Parent Page',
|
||||
name: 'pageId',
|
||||
type: 'resourceLocator',
|
||||
default: { mode: 'url', value: '' },
|
||||
required: true,
|
||||
modes: [
|
||||
{
|
||||
displayName: 'Link',
|
||||
name: 'url',
|
||||
type: 'string',
|
||||
placeholder: 'https://www.notion.so/My-Page-b4eeb113e118403aa450af65ac25f0b9',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: databasePageUrlValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Database Page URL',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: databasePageUrlExtractionRegexp,
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'ID',
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
placeholder: 'ab1545b247fb49fa92d6f4b49f4d8116',
|
||||
validation: [
|
||||
{
|
||||
type: 'regex',
|
||||
properties: {
|
||||
regex: idValidationRegexp,
|
||||
errorMessage: 'Not a valid Notion Page ID',
|
||||
},
|
||||
},
|
||||
],
|
||||
extractValue: {
|
||||
type: 'regex',
|
||||
regex: idExtractionRegexp,
|
||||
},
|
||||
url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
description: 'The Notion Database Page to create a child page for',
|
||||
},
|
||||
{
|
||||
displayName: 'Title',
|
||||
name: 'title',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
description: 'Page title. Appears at the top of the page and can be found via Quick Find.',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
...blocks('page', 'create'),
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['create'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add option',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Icon Type',
|
||||
name: 'iconType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Emoji',
|
||||
value: 'emoji',
|
||||
description: 'Use an Emoji for the icon',
|
||||
},
|
||||
{
|
||||
name: 'File',
|
||||
value: 'file',
|
||||
description: 'Use a file for the icon',
|
||||
},
|
||||
],
|
||||
default: 'emoji',
|
||||
description: 'The icon type for the page, Either a URL or an Emoji',
|
||||
},
|
||||
{
|
||||
displayName: 'Icon',
|
||||
name: 'icon',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Emoji or File URL to use as the icon',
|
||||
},
|
||||
],
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* page:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Page Link or ID',
|
||||
name: 'pageId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [1],
|
||||
resource: ['page'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
description:
|
||||
"The Page URL from Notion's 'copy link' functionality (or just the ID contained within the URL)",
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'@version': [1],
|
||||
resource: ['page'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* page:search */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Search Text',
|
||||
name: 'text',
|
||||
type: 'string',
|
||||
default: '',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
description: 'The text to search for',
|
||||
},
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['search'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: true,
|
||||
description: 'Whether to return a simplified version of the response instead of the raw data',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['page'],
|
||||
operation: ['search'],
|
||||
},
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filter',
|
||||
placeholder: 'Add Filter',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: false,
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Filter',
|
||||
name: 'filters',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Property',
|
||||
name: 'property',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Object',
|
||||
value: 'object',
|
||||
},
|
||||
],
|
||||
default: 'object',
|
||||
description: 'The name of the property to filter by',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Database',
|
||||
value: 'database',
|
||||
},
|
||||
{
|
||||
name: 'Page',
|
||||
value: 'page',
|
||||
},
|
||||
],
|
||||
default: '',
|
||||
description: 'The value of the property to filter by',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sort',
|
||||
placeholder: 'Add Sort',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: false,
|
||||
},
|
||||
default: {},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sortValue',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Direction',
|
||||
name: 'direction',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Ascending',
|
||||
value: 'ascending',
|
||||
},
|
||||
{
|
||||
name: 'Descending',
|
||||
value: 'descending',
|
||||
},
|
||||
],
|
||||
default: 'descending',
|
||||
description: 'The direction to sort',
|
||||
},
|
||||
{
|
||||
displayName: 'Timestamp',
|
||||
name: 'timestamp',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Last Edited Time',
|
||||
value: 'last_edited_time',
|
||||
},
|
||||
],
|
||||
default: 'last_edited_time',
|
||||
description: 'The name of the timestamp to sort against',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1,83 @@
|
||||
import type { INodeProperties } from 'n8n-workflow';
|
||||
|
||||
export const userOperations: INodeProperties[] = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
name: 'operation',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
name: 'Get',
|
||||
value: 'get',
|
||||
description: 'Get a user',
|
||||
action: 'Get a user',
|
||||
},
|
||||
{
|
||||
name: 'Get Many',
|
||||
value: 'getAll',
|
||||
description: 'Get many users',
|
||||
action: 'Get many users',
|
||||
},
|
||||
],
|
||||
default: 'get',
|
||||
},
|
||||
];
|
||||
|
||||
export const userFields: INodeProperties[] = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* user:get */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'User ID',
|
||||
name: 'userId',
|
||||
type: 'string',
|
||||
default: '',
|
||||
required: true,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['get'],
|
||||
},
|
||||
},
|
||||
},
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* user:getAll */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['getAll'],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Whether to return all results or only up to a given limit',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: ['user'],
|
||||
operation: ['getAll'],
|
||||
returnAll: [false],
|
||||
},
|
||||
},
|
||||
typeOptions: {
|
||||
minValue: 1,
|
||||
maxValue: 100,
|
||||
},
|
||||
default: 50,
|
||||
description: 'Max number of results to return',
|
||||
},
|
||||
];
|
||||
@@ -0,0 +1 @@
|
||||
export * as listSearch from './listSearch';
|
||||
@@ -0,0 +1,38 @@
|
||||
import type {
|
||||
IDataObject,
|
||||
ILoadOptionsFunctions,
|
||||
INodeListSearchItems,
|
||||
INodeListSearchResult,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { notionApiRequestAllItems } from '../GenericFunctions';
|
||||
|
||||
export async function getDatabases(
|
||||
this: ILoadOptionsFunctions,
|
||||
filter?: string,
|
||||
): Promise<INodeListSearchResult> {
|
||||
const returnData: INodeListSearchItems[] = [];
|
||||
const body: IDataObject = {
|
||||
page_size: 100,
|
||||
query: filter,
|
||||
filter: { property: 'object', value: 'database' },
|
||||
};
|
||||
const databases = await notionApiRequestAllItems.call(this, 'results', 'POST', '/search', body);
|
||||
for (const database of databases) {
|
||||
returnData.push({
|
||||
name: database.title[0]?.plain_text || database.id,
|
||||
value: database.id,
|
||||
url: database.url,
|
||||
});
|
||||
}
|
||||
returnData.sort((a, b) => {
|
||||
if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return { results: returnData };
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
import type { MockProxy } from 'jest-mock-extended';
|
||||
import { mock } from 'jest-mock-extended';
|
||||
import type { IExecuteFunctions, INode, INodeParameterResourceLocator } from 'n8n-workflow';
|
||||
import { NodeOperationError } from 'n8n-workflow';
|
||||
|
||||
import { databasePageUrlExtractionRegexp } from '../shared/constants';
|
||||
import { extractPageId, formatBlocks, getPageId } from '../shared/GenericFunctions';
|
||||
|
||||
describe('Test NotionV2, formatBlocks', () => {
|
||||
it('should format to_do block', () => {
|
||||
const blocks = [
|
||||
{
|
||||
type: 'to_do',
|
||||
checked: false,
|
||||
richText: false,
|
||||
textContent: 'Testing',
|
||||
},
|
||||
];
|
||||
|
||||
const result = formatBlocks(blocks);
|
||||
|
||||
expect(result).toEqual([
|
||||
{
|
||||
object: 'block',
|
||||
type: 'to_do',
|
||||
to_do: {
|
||||
checked: false,
|
||||
text: [
|
||||
{
|
||||
text: {
|
||||
content: 'Testing',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test Notion', () => {
|
||||
const baseUrl = 'https://www.notion.so/fake-instance';
|
||||
const testIds = [
|
||||
'4eb10d5001254b7faaa831d72d9445aa', // Taken from Notion
|
||||
'fffb95d3060b80309027eb9c99605ec3', // Taken from user comment
|
||||
'a6356387779d4df485449a72a408f0d4', // Random v4 UUID
|
||||
'f4c1217e48f711ef94540242ac120002', // Random v1 UUID
|
||||
];
|
||||
describe('extractPageId From URL', () => {
|
||||
// RLC does some Regex extraction before extractPageId is called
|
||||
const extractIdFromUrl = (url: string): string => {
|
||||
const match = url.match(databasePageUrlExtractionRegexp);
|
||||
return match ? match[1] : url;
|
||||
};
|
||||
|
||||
test('should return the part after "p="', () => {
|
||||
for (const testId of testIds) {
|
||||
const page = `${baseUrl}?p=${testId}`;
|
||||
const result = extractPageId(extractIdFromUrl(page));
|
||||
expect(result).toBe(testId);
|
||||
}
|
||||
});
|
||||
|
||||
test('should return the last part after splitting by "-" when URL contains multiple "-"', () => {
|
||||
for (const testId of testIds) {
|
||||
const page = `${baseUrl}/some-page-${testId}`;
|
||||
const result = extractPageId(extractIdFromUrl(page));
|
||||
expect(result).toBe(testId);
|
||||
}
|
||||
});
|
||||
|
||||
test('should return the last part after splitting by "-" when URL contains one "-"', () => {
|
||||
for (const testId of testIds) {
|
||||
const page = `${baseUrl}/1-${testId}`;
|
||||
const result = extractPageId(extractIdFromUrl(page));
|
||||
expect(result).toBe(testId);
|
||||
}
|
||||
});
|
||||
|
||||
test('should return just the id when there is an instance name', () => {
|
||||
for (const testId of testIds) {
|
||||
const page = `${baseUrl}/${testId}`;
|
||||
const result = extractPageId(extractIdFromUrl(page));
|
||||
expect(result).toBe(testId);
|
||||
}
|
||||
});
|
||||
|
||||
test('should return the id when there is no instance name', () => {
|
||||
for (const testId of testIds) {
|
||||
const page = `https://www.notion.so/${testId}`;
|
||||
const result = extractPageId(extractIdFromUrl(page));
|
||||
expect(result).toBe(testId);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test Notion, getPageId', () => {
|
||||
let mockExecuteFunctions: MockProxy<IExecuteFunctions>;
|
||||
const id = '3ab5bc794647496dac48feca926813fd';
|
||||
|
||||
beforeEach(() => {
|
||||
mockExecuteFunctions = mock<IExecuteFunctions>();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should return page ID directly when mode is id', () => {
|
||||
const page = {
|
||||
mode: 'id',
|
||||
value: id,
|
||||
} as INodeParameterResourceLocator;
|
||||
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValue(page);
|
||||
|
||||
const result = getPageId.call(mockExecuteFunctions, 0);
|
||||
expect(result).toBe(id);
|
||||
expect(mockExecuteFunctions.getNodeParameter).toHaveBeenCalledWith('pageId', 0, {});
|
||||
});
|
||||
|
||||
it('should extract page ID from URL with p parameter', () => {
|
||||
const page = {
|
||||
mode: 'url',
|
||||
value: `https://www.notion.so/xxxxx?v=xxxxx&p=${id}&pm=s`,
|
||||
} as INodeParameterResourceLocator;
|
||||
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValue(page);
|
||||
|
||||
const result = getPageId.call(mockExecuteFunctions, 0);
|
||||
expect(result).toBe(id);
|
||||
});
|
||||
|
||||
it('should extract page ID from URL using regex', () => {
|
||||
const page = {
|
||||
mode: 'url',
|
||||
value: `https://www.notion.so/page-name-${id}`,
|
||||
} as INodeParameterResourceLocator;
|
||||
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValue(page);
|
||||
|
||||
const result = getPageId.call(mockExecuteFunctions, 0);
|
||||
expect(result).toBe(id);
|
||||
});
|
||||
|
||||
it('should throw error when page ID cannot be extracted', () => {
|
||||
const page = {
|
||||
mode: 'url',
|
||||
value: 'https://www.notion.so/invalid-url',
|
||||
} as INodeParameterResourceLocator;
|
||||
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValue(page);
|
||||
mockExecuteFunctions.getNode.mockReturnValue(mock<INode>({ name: 'Notion', type: 'notion' }));
|
||||
|
||||
expect(() => getPageId.call(mockExecuteFunctions, 0)).toThrow(NodeOperationError);
|
||||
expect(() => getPageId.call(mockExecuteFunctions, 0)).toThrow(
|
||||
'Could not extract page ID from URL: https://www.notion.so/invalid-url',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error when page value is empty', () => {
|
||||
const page = {
|
||||
mode: 'url',
|
||||
value: '',
|
||||
} as INodeParameterResourceLocator;
|
||||
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValue(page);
|
||||
mockExecuteFunctions.getNode.mockReturnValue(mock<INode>({ name: 'Notion', type: 'notion' }));
|
||||
|
||||
expect(() => getPageId.call(mockExecuteFunctions, 0)).toThrow(NodeOperationError);
|
||||
expect(() => getPageId.call(mockExecuteFunctions, 0)).toThrow(
|
||||
'Could not extract page ID from URL: ',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error when page value is undefined', () => {
|
||||
const page = {
|
||||
mode: 'url',
|
||||
value: undefined,
|
||||
} as INodeParameterResourceLocator;
|
||||
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValue(page);
|
||||
mockExecuteFunctions.getNode.mockReturnValue(mock<INode>({ name: 'Notion', type: 'notion' }));
|
||||
|
||||
expect(() => getPageId.call(mockExecuteFunctions, 0)).toThrow(NodeOperationError);
|
||||
expect(() => getPageId.call(mockExecuteFunctions, 0)).toThrow(
|
||||
'Could not extract page ID from URL: undefined',
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw error when page value is not a string', () => {
|
||||
const page = {
|
||||
mode: 'url',
|
||||
value: 123 as any,
|
||||
} as INodeParameterResourceLocator;
|
||||
|
||||
mockExecuteFunctions.getNodeParameter.mockReturnValue(page);
|
||||
mockExecuteFunctions.getNode.mockReturnValue(mock<INode>({ name: 'Notion', type: 'notion' }));
|
||||
|
||||
expect(() => getPageId.call(mockExecuteFunctions, 0)).toThrow(NodeOperationError);
|
||||
expect(() => getPageId.call(mockExecuteFunctions, 0)).toThrow(
|
||||
'Could not extract page ID from URL: 123',
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,421 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
object: 'list',
|
||||
results: [
|
||||
{
|
||||
object: 'block',
|
||||
id: '15bfb9cb-4cf0-8162-bd53-fc201157675f',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2024-12-13T03:40:00.000Z',
|
||||
last_edited_time: '2024-12-13T03:40:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'paragraph',
|
||||
paragraph: {
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'new text',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'new text',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: '15bfb9cb-4cf0-8104-8d3f-c8ca8919e791',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2024-12-13T03:40:00.000Z',
|
||||
last_edited_time: '2024-12-13T03:40:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'heading_1',
|
||||
heading_1: {
|
||||
is_toggleable: false,
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'h1',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'h1',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: '15bfb9cb-4cf0-814d-b4ad-f65a2c558bb9',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2024-12-13T03:40:00.000Z',
|
||||
last_edited_time: '2024-12-13T03:40:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'heading_2',
|
||||
heading_2: {
|
||||
is_toggleable: false,
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'h2',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'h2',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: '15bfb9cb-4cf0-8135-9e43-f3f8a21e2e86',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2024-12-13T03:40:00.000Z',
|
||||
last_edited_time: '2024-12-13T03:40:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'heading_3',
|
||||
heading_3: {
|
||||
is_toggleable: false,
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'h3',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'h3',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: '15bfb9cb-4cf0-816b-9457-efba183a957c',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2024-12-13T03:40:00.000Z',
|
||||
last_edited_time: '2024-12-13T03:40:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'toggle',
|
||||
toggle: {
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'toggle',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'toggle',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: '15bfb9cb-4cf0-814f-9928-ed87ed0d9470',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2024-12-13T03:40:00.000Z',
|
||||
last_edited_time: '2024-12-13T03:40:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'to_do',
|
||||
to_do: {
|
||||
checked: false,
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'todo',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'todo',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: '15bfb9cb-4cf0-812d-95e9-dc8ddc3153dd',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2024-12-13T03:40:00.000Z',
|
||||
last_edited_time: '2024-12-13T03:40:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'bulleted_list_item',
|
||||
bulleted_list_item: {
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'bullet 1',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'bullet 1',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: '15bfb9cb-4cf0-8106-9a25-d3859984ce34',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2024-12-13T03:40:00.000Z',
|
||||
last_edited_time: '2024-12-13T03:40:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'numbered_list_item',
|
||||
numbered_list_item: {
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'point 1',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'point 1',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: '15bfb9cb-4cf0-81b1-a6f1-eac377c4d163',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2024-12-13T03:40:00.000Z',
|
||||
last_edited_time: '2024-12-13T03:40:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'paragraph',
|
||||
paragraph: {
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: '',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: '',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
next_cursor: null,
|
||||
has_more: false,
|
||||
request_id: '33358f1b-fc4d-4387-8d95-43c7d03519a5',
|
||||
};
|
||||
|
||||
describe('Test NotionV2, block => append', () => {
|
||||
nock('https://api.notion.com')
|
||||
.patch('/v1/blocks/90e03468f8aa457695da02ccad963040/children')
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['append.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,535 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "block",
|
||||
"blockId": {
|
||||
"__rl": true,
|
||||
"value": "https://www.notion.so/Block-Test-88188cbb303e4f44847f27d24bd7ad8e?pvs=4#90e03468f8aa457695da02ccad963040",
|
||||
"mode": "url"
|
||||
},
|
||||
"blockUi": {
|
||||
"blockValues": [
|
||||
{
|
||||
"richText": true,
|
||||
"text": {
|
||||
"text": [
|
||||
{
|
||||
"text": "new text",
|
||||
"annotationUi": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "heading_1",
|
||||
"textContent": "h1"
|
||||
},
|
||||
{
|
||||
"type": "heading_2",
|
||||
"textContent": "h2"
|
||||
},
|
||||
{
|
||||
"type": "heading_3",
|
||||
"textContent": "h3"
|
||||
},
|
||||
{
|
||||
"type": "toggle",
|
||||
"textContent": "toggle"
|
||||
},
|
||||
{
|
||||
"type": "to_do",
|
||||
"textContent": "todo"
|
||||
},
|
||||
{
|
||||
"type": "bulleted_list_item",
|
||||
"textContent": "bullet 1"
|
||||
},
|
||||
{
|
||||
"type": "numbered_list_item",
|
||||
"textContent": "point 1"
|
||||
},
|
||||
{}
|
||||
]
|
||||
}
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"object": "list",
|
||||
"results": [
|
||||
{
|
||||
"object": "block",
|
||||
"id": "15bfb9cb-4cf0-8162-bd53-fc201157675f",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"created_time": "2024-12-13T03:40:00.000Z",
|
||||
"last_edited_time": "2024-12-13T03:40:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"color": "default",
|
||||
"text": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": {
|
||||
"content": "new text",
|
||||
"link": null
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "new text",
|
||||
"href": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "15bfb9cb-4cf0-8104-8d3f-c8ca8919e791",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"created_time": "2024-12-13T03:40:00.000Z",
|
||||
"last_edited_time": "2024-12-13T03:40:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "heading_1",
|
||||
"heading_1": {
|
||||
"is_toggleable": false,
|
||||
"color": "default",
|
||||
"text": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": {
|
||||
"content": "h1",
|
||||
"link": null
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "h1",
|
||||
"href": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "15bfb9cb-4cf0-814d-b4ad-f65a2c558bb9",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"created_time": "2024-12-13T03:40:00.000Z",
|
||||
"last_edited_time": "2024-12-13T03:40:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "heading_2",
|
||||
"heading_2": {
|
||||
"is_toggleable": false,
|
||||
"color": "default",
|
||||
"text": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": {
|
||||
"content": "h2",
|
||||
"link": null
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "h2",
|
||||
"href": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "15bfb9cb-4cf0-8135-9e43-f3f8a21e2e86",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"created_time": "2024-12-13T03:40:00.000Z",
|
||||
"last_edited_time": "2024-12-13T03:40:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "heading_3",
|
||||
"heading_3": {
|
||||
"is_toggleable": false,
|
||||
"color": "default",
|
||||
"text": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": {
|
||||
"content": "h3",
|
||||
"link": null
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "h3",
|
||||
"href": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "15bfb9cb-4cf0-816b-9457-efba183a957c",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"created_time": "2024-12-13T03:40:00.000Z",
|
||||
"last_edited_time": "2024-12-13T03:40:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "toggle",
|
||||
"toggle": {
|
||||
"color": "default",
|
||||
"text": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": {
|
||||
"content": "toggle",
|
||||
"link": null
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "toggle",
|
||||
"href": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "15bfb9cb-4cf0-814f-9928-ed87ed0d9470",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"created_time": "2024-12-13T03:40:00.000Z",
|
||||
"last_edited_time": "2024-12-13T03:40:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "to_do",
|
||||
"to_do": {
|
||||
"checked": false,
|
||||
"color": "default",
|
||||
"text": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": {
|
||||
"content": "todo",
|
||||
"link": null
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "todo",
|
||||
"href": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "15bfb9cb-4cf0-812d-95e9-dc8ddc3153dd",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"created_time": "2024-12-13T03:40:00.000Z",
|
||||
"last_edited_time": "2024-12-13T03:40:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "bulleted_list_item",
|
||||
"bulleted_list_item": {
|
||||
"color": "default",
|
||||
"text": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": {
|
||||
"content": "bullet 1",
|
||||
"link": null
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "bullet 1",
|
||||
"href": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "15bfb9cb-4cf0-8106-9a25-d3859984ce34",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"created_time": "2024-12-13T03:40:00.000Z",
|
||||
"last_edited_time": "2024-12-13T03:40:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "numbered_list_item",
|
||||
"numbered_list_item": {
|
||||
"color": "default",
|
||||
"text": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": {
|
||||
"content": "point 1",
|
||||
"link": null
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "point 1",
|
||||
"href": null
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"object": "block",
|
||||
"id": "15bfb9cb-4cf0-81b1-a6f1-eac377c4d163",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"created_time": "2024-12-13T03:40:00.000Z",
|
||||
"last_edited_time": "2024-12-13T03:40:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"paragraph": {
|
||||
"color": "default",
|
||||
"text": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": {
|
||||
"content": "",
|
||||
"link": null
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "",
|
||||
"href": null
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"next_cursor": null,
|
||||
"has_more": false,
|
||||
"request_id": "33358f1b-fc4d-4387-8d95-43c7d03519a5"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "87575721-cf21-472f-a9f0-24aa31c8100f",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
results: [
|
||||
{
|
||||
object: 'block',
|
||||
id: 'b14bdaaf-b7e9-48c9-a7fa-1b9e1e2092ae',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2023-11-23T10:42:00.000Z',
|
||||
last_edited_time: '2024-12-13T03:35:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
has_children: true,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'toggle',
|
||||
toggle: {
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'Drop down First',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'Drop down First',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: 'de572f5d-ff5c-4c13-a879-efc20fe47db0',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2023-11-23T10:42:00.000Z',
|
||||
last_edited_time: '2024-03-11T12:39:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
has_children: true,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'bulleted_list_item',
|
||||
bulleted_list_item: {
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'Bullet Point Second',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'Bullet Point Second',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: 'c98cf981-c967-47f5-9948-4aa1be9ce9d0',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2023-11-24T04:41:00.000Z',
|
||||
last_edited_time: '2024-12-13T03:35:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'heading_2',
|
||||
heading_2: {
|
||||
is_toggleable: false,
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'Hello World',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'Hello World',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: '527a0555-a486-401e-93a8-19819615c132',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2023-11-23T10:42:00.000Z',
|
||||
last_edited_time: '2023-11-23T10:43:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'child_page',
|
||||
child_page: {
|
||||
title: 'Page Third',
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
id: '15bfb9cb-4cf0-81b1-a6f1-eac377c4d163',
|
||||
parent: {
|
||||
type: 'block_id',
|
||||
block_id: '90e03468-f8aa-4576-95da-02ccad963040',
|
||||
},
|
||||
created_time: '2024-12-13T03:40:00.000Z',
|
||||
last_edited_time: '2024-12-13T06:15:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
has_children: false,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
type: 'paragraph',
|
||||
paragraph: {
|
||||
color: 'default',
|
||||
text: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: '',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: '',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
has_more: false,
|
||||
};
|
||||
|
||||
describe('Test NotionV2, block => getAll', () => {
|
||||
nock('https://api.notion.com')
|
||||
.get('/v1/blocks/90e03468f8aa457695da02ccad963040/children')
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['getAll.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,188 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "block",
|
||||
"operation": "getAll",
|
||||
"blockId": {
|
||||
"__rl": true,
|
||||
"value": "https://www.notion.so/Block-Test-88188cbb303e4f44847f27d24bd7ad8e?pvs=4#90e03468f8aa457695da02ccad963040",
|
||||
"mode": "url"
|
||||
},
|
||||
"returnAll": true
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"object": "block",
|
||||
"parent_id": "90e03468f8aa457695da02ccad963040",
|
||||
"id": "b14bdaaf-b7e9-48c9-a7fa-1b9e1e2092ae",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "88f72c1a-07ed-4bae-9fa0-231365d813d9"
|
||||
},
|
||||
"has_children": true,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "toggle",
|
||||
"root_id": "90e03468f8aa457695da02ccad963040",
|
||||
"content": "Drop down First"
|
||||
}
|
||||
},
|
||||
{
|
||||
"json": {
|
||||
"object": "block",
|
||||
"parent_id": "90e03468f8aa457695da02ccad963040",
|
||||
"id": "de572f5d-ff5c-4c13-a879-efc20fe47db0",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324"
|
||||
},
|
||||
"has_children": true,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "bulleted_list_item",
|
||||
"root_id": "90e03468f8aa457695da02ccad963040",
|
||||
"content": "Bullet Point Second"
|
||||
}
|
||||
},
|
||||
{
|
||||
"json": {
|
||||
"object": "block",
|
||||
"parent_id": "90e03468f8aa457695da02ccad963040",
|
||||
"id": "c98cf981-c967-47f5-9948-4aa1be9ce9d0",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "88f72c1a-07ed-4bae-9fa0-231365d813d9"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "heading_2",
|
||||
"root_id": "90e03468f8aa457695da02ccad963040",
|
||||
"content": "Hello World"
|
||||
}
|
||||
},
|
||||
{
|
||||
"json": {
|
||||
"object": "block",
|
||||
"parent_id": "90e03468f8aa457695da02ccad963040",
|
||||
"id": "527a0555-a486-401e-93a8-19819615c132",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "88f72c1a-07ed-4bae-9fa0-231365d813d9"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "child_page",
|
||||
"root_id": "90e03468f8aa457695da02ccad963040",
|
||||
"content": "Page Third"
|
||||
}
|
||||
},
|
||||
{
|
||||
"json": {
|
||||
"object": "block",
|
||||
"parent_id": "90e03468f8aa457695da02ccad963040",
|
||||
"id": "15bfb9cb-4cf0-81b1-a6f1-eac377c4d163",
|
||||
"parent": {
|
||||
"type": "block_id",
|
||||
"block_id": "90e03468-f8aa-4576-95da-02ccad963040"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "88f72c1a-07ed-4bae-9fa0-231365d813d9"
|
||||
},
|
||||
"has_children": false,
|
||||
"archived": false,
|
||||
"in_trash": false,
|
||||
"type": "paragraph",
|
||||
"root_id": "90e03468f8aa457695da02ccad963040",
|
||||
"content": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "3edb0c05-7e84-4953-a6a5-86c3c6824403",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
object: 'database',
|
||||
id: '138fb9cb-4cf0-804c-8663-d8ecdd5e692f',
|
||||
cover: null,
|
||||
icon: null,
|
||||
created_time: '2024-11-08T07:59:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_time: '2024-11-08T07:59:00.000Z',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'TEST_DB',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'TEST_DB',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
description: [],
|
||||
is_inline: false,
|
||||
properties: {
|
||||
Tags: {
|
||||
id: '%40~Tp',
|
||||
name: 'Tags',
|
||||
type: 'multi_select',
|
||||
multi_select: {
|
||||
options: [],
|
||||
},
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
name: 'Name',
|
||||
type: 'title',
|
||||
title: {},
|
||||
},
|
||||
},
|
||||
parent: {
|
||||
type: 'page_id',
|
||||
page_id: 'cc3d2b3c-f31a-4773-ab39-17a60c54567a',
|
||||
},
|
||||
url: 'https://www.notion.so/138fb9cb4cf0804c8663d8ecdd5e692f',
|
||||
public_url: null,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
request_id: 'd22a9046-be0d-4ef5-b551-8691da552d47',
|
||||
};
|
||||
|
||||
describe('Test NotionV2, database => get', () => {
|
||||
nock('https://api.notion.com')
|
||||
.get('/v1/databases/138fb9cb-4cf0-804c-8663-d8ecdd5e692f')
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['get.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "database",
|
||||
"databaseId": {
|
||||
"__rl": true,
|
||||
"value": "138fb9cb-4cf0-804c-8663-d8ecdd5e692f",
|
||||
"mode": "list",
|
||||
"cachedResultName": "TEST_DB",
|
||||
"cachedResultUrl": "https://www.notion.so/138fb9cb4cf0804c8663d8ecdd5e692f"
|
||||
}
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"id": "138fb9cb-4cf0-804c-8663-d8ecdd5e692f",
|
||||
"name": "TEST_DB",
|
||||
"url": "https://www.notion.so/138fb9cb4cf0804c8663d8ecdd5e692f"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "9f59436f-17e7-4c9d-a550-a594bb15618f",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
results: [
|
||||
{
|
||||
object: 'database',
|
||||
id: '138fb9cb-4cf0-804c-8663-d8ecdd5e692f',
|
||||
cover: null,
|
||||
icon: null,
|
||||
created_time: '2024-11-08T07:59:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_time: '2024-11-08T07:59:00.000Z',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'TEST_DB',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'TEST_DB',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
description: [],
|
||||
is_inline: false,
|
||||
properties: {
|
||||
Tags: {
|
||||
id: '%40~Tp',
|
||||
name: 'Tags',
|
||||
type: 'multi_select',
|
||||
multi_select: {
|
||||
options: [],
|
||||
},
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
name: 'Name',
|
||||
type: 'title',
|
||||
title: {},
|
||||
},
|
||||
},
|
||||
parent: {
|
||||
type: 'page_id',
|
||||
page_id: 'cc3d2b3c-f31a-4773-ab39-17a60c54567a',
|
||||
},
|
||||
url: 'https://www.notion.so/138fb9cb4cf0804c8663d8ecdd5e692f',
|
||||
public_url: null,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
},
|
||||
{
|
||||
object: 'database',
|
||||
id: 'f7216195-e0d4-46cd-a2d3-587a05baf472',
|
||||
cover: null,
|
||||
icon: null,
|
||||
created_time: '2022-03-07T11:25:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_time: '2024-11-08T07:54:00.000Z',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'ListDatabase',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'ListDatabase',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
description: [],
|
||||
is_inline: false,
|
||||
properties: {
|
||||
Email: {
|
||||
id: 'Fitu',
|
||||
name: 'Email',
|
||||
type: 'email',
|
||||
email: {},
|
||||
},
|
||||
'Last edited by': {
|
||||
id: 'XZ~H',
|
||||
name: 'Last edited by',
|
||||
type: 'last_edited_by',
|
||||
last_edited_by: {},
|
||||
},
|
||||
Tags: {
|
||||
id: 'a%7BRG',
|
||||
name: 'Tags',
|
||||
type: 'multi_select',
|
||||
multi_select: {
|
||||
options: [],
|
||||
},
|
||||
},
|
||||
Created: {
|
||||
id: 'eqq~',
|
||||
name: 'Created',
|
||||
type: 'created_time',
|
||||
created_time: {},
|
||||
},
|
||||
Status: {
|
||||
id: 'nZEQ',
|
||||
name: 'Status',
|
||||
type: 'status',
|
||||
status: {
|
||||
options: [
|
||||
{
|
||||
id: '70312bf9-84d5-40e6-b1eb-d71798ee556f',
|
||||
name: 'Not started',
|
||||
color: 'default',
|
||||
description: null,
|
||||
},
|
||||
{
|
||||
id: '02a6bb40-3f4b-47d6-818d-6a4129cc6091',
|
||||
name: 'In progress',
|
||||
color: 'gray',
|
||||
description: null,
|
||||
},
|
||||
{
|
||||
id: 'a3c13d01-63b2-4571-8a02-8c1801649af7',
|
||||
name: 'Done',
|
||||
color: 'green',
|
||||
description: null,
|
||||
},
|
||||
],
|
||||
groups: [
|
||||
{
|
||||
id: '82e2022c-001d-47ac-a8b8-243ef7fac352',
|
||||
name: 'To-do',
|
||||
color: 'gray',
|
||||
option_ids: ['70312bf9-84d5-40e6-b1eb-d71798ee556f'],
|
||||
},
|
||||
{
|
||||
id: '296000d7-287e-4121-9445-98fa8f7de298',
|
||||
name: 'In progress',
|
||||
color: 'blue',
|
||||
option_ids: ['02a6bb40-3f4b-47d6-818d-6a4129cc6091'],
|
||||
},
|
||||
{
|
||||
id: 'db7689ae-127d-4218-8b3c-306e59e02070',
|
||||
name: 'Complete',
|
||||
color: 'green',
|
||||
option_ids: ['a3c13d01-63b2-4571-8a02-8c1801649af7'],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
name: 'Name',
|
||||
type: 'title',
|
||||
title: {},
|
||||
},
|
||||
},
|
||||
parent: {
|
||||
type: 'page_id',
|
||||
page_id: 'cc3d2b3c-f31a-4773-ab39-17a60c54567a',
|
||||
},
|
||||
url: 'https://www.notion.so/f7216195e0d446cda2d3587a05baf472',
|
||||
public_url: 'https://pleasant-halloumi-63e.notion.site/f7216195e0d446cda2d3587a05baf472',
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
},
|
||||
{
|
||||
object: 'database',
|
||||
id: 'e9c354e3-e506-4c42-83e2-d9c81a083f05',
|
||||
cover: null,
|
||||
icon: null,
|
||||
created_time: '2022-03-07T11:05:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_time: '2023-09-29T08:00:00.000Z',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'n8n-trigger',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'n8n-trigger',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
description: [],
|
||||
is_inline: false,
|
||||
properties: {
|
||||
Total: {
|
||||
id: 'A%3DdW',
|
||||
name: 'Total',
|
||||
type: 'formula',
|
||||
formula: {
|
||||
expression:
|
||||
'((({{notion:block_property:n%7DI%5E:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}} + {{notion:block_property:MH~%3B:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}) - {{notion:block_property:MwMd:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}) + {{notion:block_property:fJea:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}) - {{notion:block_property:rSrM:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}',
|
||||
},
|
||||
},
|
||||
'Total Incomes': {
|
||||
id: 'MH~%3B',
|
||||
name: 'Total Incomes',
|
||||
type: 'number',
|
||||
number: {
|
||||
format: 'number',
|
||||
},
|
||||
},
|
||||
'Total Expenses': {
|
||||
id: 'MwMd',
|
||||
name: 'Total Expenses',
|
||||
type: 'number',
|
||||
number: {
|
||||
format: 'number',
|
||||
},
|
||||
},
|
||||
'Created time': {
|
||||
id: 'Z%3BGM',
|
||||
name: 'Created time',
|
||||
type: 'created_time',
|
||||
created_time: {},
|
||||
},
|
||||
'Last edited time': {
|
||||
id: '%60%5ElG',
|
||||
name: 'Last edited time',
|
||||
type: 'last_edited_time',
|
||||
last_edited_time: {},
|
||||
},
|
||||
'Total Transfer-In': {
|
||||
id: 'fJea',
|
||||
name: 'Total Transfer-In',
|
||||
type: 'number',
|
||||
number: {
|
||||
format: 'number',
|
||||
},
|
||||
},
|
||||
'Starting Balance': {
|
||||
id: 'n%7DI%5E',
|
||||
name: 'Starting Balance',
|
||||
type: 'number',
|
||||
number: {
|
||||
format: 'number',
|
||||
},
|
||||
},
|
||||
'Total Transfer-Out': {
|
||||
id: 'rSrM',
|
||||
name: 'Total Transfer-Out',
|
||||
type: 'number',
|
||||
number: {
|
||||
format: 'number',
|
||||
},
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
name: 'Name',
|
||||
type: 'title',
|
||||
title: {},
|
||||
},
|
||||
},
|
||||
parent: {
|
||||
type: 'page_id',
|
||||
page_id: 'cc3d2b3c-f31a-4773-ab39-17a60c54567a',
|
||||
},
|
||||
url: 'https://www.notion.so/e9c354e3e5064c4283e2d9c81a083f05',
|
||||
public_url: null,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
},
|
||||
],
|
||||
has_more: false,
|
||||
};
|
||||
|
||||
describe('Test NotionV2, database => getAll', () => {
|
||||
nock('https://api.notion.com')
|
||||
.post('/v1/search', { filter: { property: 'object', value: 'database' } })
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['getAll.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,99 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "database",
|
||||
"operation": "getAll",
|
||||
"returnAll": true
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"id": "138fb9cb-4cf0-804c-8663-d8ecdd5e692f",
|
||||
"name": "TEST_DB",
|
||||
"url": "https://www.notion.so/138fb9cb4cf0804c8663d8ecdd5e692f"
|
||||
}
|
||||
},
|
||||
{
|
||||
"json": {
|
||||
"id": "f7216195-e0d4-46cd-a2d3-587a05baf472",
|
||||
"name": "ListDatabase",
|
||||
"url": "https://www.notion.so/f7216195e0d446cda2d3587a05baf472"
|
||||
}
|
||||
},
|
||||
{
|
||||
"json": {
|
||||
"id": "e9c354e3-e506-4c42-83e2-d9c81a083f05",
|
||||
"name": "n8n-trigger",
|
||||
"url": "https://www.notion.so/e9c354e3e5064c4283e2d9c81a083f05"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "c9094e39-7195-4d4c-9e08-928415e1902b",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
results: [
|
||||
{
|
||||
object: 'database',
|
||||
id: 'e9c354e3-e506-4c42-83e2-d9c81a083f05',
|
||||
cover: null,
|
||||
icon: null,
|
||||
created_time: '2022-03-07T11:05:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_time: '2023-09-29T08:00:00.000Z',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'n8n-trigger',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'n8n-trigger',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
description: [],
|
||||
is_inline: false,
|
||||
properties: {
|
||||
Total: {
|
||||
id: 'A%3DdW',
|
||||
name: 'Total',
|
||||
type: 'formula',
|
||||
formula: {
|
||||
expression:
|
||||
'((({{notion:block_property:n%7DI%5E:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}} + {{notion:block_property:MH~%3B:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}) - {{notion:block_property:MwMd:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}) + {{notion:block_property:fJea:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}) - {{notion:block_property:rSrM:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}',
|
||||
},
|
||||
},
|
||||
'Total Incomes': {
|
||||
id: 'MH~%3B',
|
||||
name: 'Total Incomes',
|
||||
type: 'number',
|
||||
number: {
|
||||
format: 'number',
|
||||
},
|
||||
},
|
||||
'Total Expenses': {
|
||||
id: 'MwMd',
|
||||
name: 'Total Expenses',
|
||||
type: 'number',
|
||||
number: {
|
||||
format: 'number',
|
||||
},
|
||||
},
|
||||
'Created time': {
|
||||
id: 'Z%3BGM',
|
||||
name: 'Created time',
|
||||
type: 'created_time',
|
||||
created_time: {},
|
||||
},
|
||||
'Last edited time': {
|
||||
id: '%60%5ElG',
|
||||
name: 'Last edited time',
|
||||
type: 'last_edited_time',
|
||||
last_edited_time: {},
|
||||
},
|
||||
'Total Transfer-In': {
|
||||
id: 'fJea',
|
||||
name: 'Total Transfer-In',
|
||||
type: 'number',
|
||||
number: {
|
||||
format: 'number',
|
||||
},
|
||||
},
|
||||
'Starting Balance': {
|
||||
id: 'n%7DI%5E',
|
||||
name: 'Starting Balance',
|
||||
type: 'number',
|
||||
number: {
|
||||
format: 'number',
|
||||
},
|
||||
},
|
||||
'Total Transfer-Out': {
|
||||
id: 'rSrM',
|
||||
name: 'Total Transfer-Out',
|
||||
type: 'number',
|
||||
number: {
|
||||
format: 'number',
|
||||
},
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
name: 'Name',
|
||||
type: 'title',
|
||||
title: {},
|
||||
},
|
||||
},
|
||||
parent: {
|
||||
type: 'page_id',
|
||||
page_id: 'cc3d2b3c-f31a-4773-ab39-17a60c54567a',
|
||||
},
|
||||
url: 'https://www.notion.so/e9c354e3e5064c4283e2d9c81a083f05',
|
||||
public_url: null,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
},
|
||||
{
|
||||
object: 'database',
|
||||
id: '138fb9cb-4cf0-804c-8663-d8ecdd5e692f',
|
||||
cover: null,
|
||||
icon: null,
|
||||
created_time: '2024-11-08T07:59:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: '88f72c1a-07ed-4bae-9fa0-231365d813d9',
|
||||
},
|
||||
last_edited_time: '2024-11-08T07:59:00.000Z',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'TEST_DB',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'TEST_DB',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
description: [],
|
||||
is_inline: false,
|
||||
properties: {
|
||||
Tags: {
|
||||
id: '%40~Tp',
|
||||
name: 'Tags',
|
||||
type: 'multi_select',
|
||||
multi_select: {
|
||||
options: [],
|
||||
},
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
name: 'Name',
|
||||
type: 'title',
|
||||
title: {},
|
||||
},
|
||||
},
|
||||
parent: {
|
||||
type: 'page_id',
|
||||
page_id: 'cc3d2b3c-f31a-4773-ab39-17a60c54567a',
|
||||
},
|
||||
url: 'https://www.notion.so/138fb9cb4cf0804c8663d8ecdd5e692f',
|
||||
public_url: null,
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
},
|
||||
],
|
||||
has_more: false,
|
||||
};
|
||||
|
||||
describe('Test NotionV2, database => search', () => {
|
||||
nock('https://api.notion.com')
|
||||
.post('/v1/search', {
|
||||
filter: { property: 'object', value: 'database' },
|
||||
query: 't',
|
||||
sort: { direction: 'ascending', timestamp: 'last_edited_time' },
|
||||
})
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['search.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,265 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "database",
|
||||
"operation": "search",
|
||||
"text": "t",
|
||||
"limit": 2,
|
||||
"simple": false,
|
||||
"options": {
|
||||
"sort": {
|
||||
"sortValue": {
|
||||
"direction": "ascending"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"object": "database",
|
||||
"id": "e9c354e3-e506-4c42-83e2-d9c81a083f05",
|
||||
"cover": null,
|
||||
"icon": null,
|
||||
"created_time": "2022-03-07T11:05:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "88f72c1a-07ed-4bae-9fa0-231365d813d9"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "88f72c1a-07ed-4bae-9fa0-231365d813d9"
|
||||
},
|
||||
"last_edited_time": "2023-09-29T08:00:00.000Z",
|
||||
"title": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": {
|
||||
"content": "n8n-trigger",
|
||||
"link": null
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "n8n-trigger",
|
||||
"href": null
|
||||
}
|
||||
],
|
||||
"description": [],
|
||||
"is_inline": false,
|
||||
"properties": {
|
||||
"Total": {
|
||||
"id": "A%3DdW",
|
||||
"name": "Total",
|
||||
"type": "formula",
|
||||
"formula": {
|
||||
"expression": "((({{notion:block_property:n%7DI%5E:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}} + {{notion:block_property:MH~%3B:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}) - {{notion:block_property:MwMd:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}) + {{notion:block_property:fJea:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}) - {{notion:block_property:rSrM:00000000-0000-0000-0000-000000000000:fe91914e-2dc5-4510-82f8-399dd9b2daf8}}"
|
||||
}
|
||||
},
|
||||
"Total Incomes": {
|
||||
"id": "MH~%3B",
|
||||
"name": "Total Incomes",
|
||||
"type": "number",
|
||||
"number": {
|
||||
"format": "number"
|
||||
}
|
||||
},
|
||||
"Total Expenses": {
|
||||
"id": "MwMd",
|
||||
"name": "Total Expenses",
|
||||
"type": "number",
|
||||
"number": {
|
||||
"format": "number"
|
||||
}
|
||||
},
|
||||
"Created time": {
|
||||
"id": "Z%3BGM",
|
||||
"name": "Created time",
|
||||
"type": "created_time",
|
||||
"created_time": {}
|
||||
},
|
||||
"Last edited time": {
|
||||
"id": "%60%5ElG",
|
||||
"name": "Last edited time",
|
||||
"type": "last_edited_time",
|
||||
"last_edited_time": {}
|
||||
},
|
||||
"Total Transfer-In": {
|
||||
"id": "fJea",
|
||||
"name": "Total Transfer-In",
|
||||
"type": "number",
|
||||
"number": {
|
||||
"format": "number"
|
||||
}
|
||||
},
|
||||
"Starting Balance": {
|
||||
"id": "n%7DI%5E",
|
||||
"name": "Starting Balance",
|
||||
"type": "number",
|
||||
"number": {
|
||||
"format": "number"
|
||||
}
|
||||
},
|
||||
"Total Transfer-Out": {
|
||||
"id": "rSrM",
|
||||
"name": "Total Transfer-Out",
|
||||
"type": "number",
|
||||
"number": {
|
||||
"format": "number"
|
||||
}
|
||||
},
|
||||
"Name": {
|
||||
"id": "title",
|
||||
"name": "Name",
|
||||
"type": "title",
|
||||
"title": {}
|
||||
}
|
||||
},
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "cc3d2b3c-f31a-4773-ab39-17a60c54567a"
|
||||
},
|
||||
"url": "https://www.notion.so/e9c354e3e5064c4283e2d9c81a083f05",
|
||||
"public_url": null,
|
||||
"archived": false,
|
||||
"in_trash": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"json": {
|
||||
"object": "database",
|
||||
"id": "138fb9cb-4cf0-804c-8663-d8ecdd5e692f",
|
||||
"cover": null,
|
||||
"icon": null,
|
||||
"created_time": "2024-11-08T07:59:00.000Z",
|
||||
"created_by": {
|
||||
"object": "user",
|
||||
"id": "88f72c1a-07ed-4bae-9fa0-231365d813d9"
|
||||
},
|
||||
"last_edited_by": {
|
||||
"object": "user",
|
||||
"id": "88f72c1a-07ed-4bae-9fa0-231365d813d9"
|
||||
},
|
||||
"last_edited_time": "2024-11-08T07:59:00.000Z",
|
||||
"title": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": {
|
||||
"content": "TEST_DB",
|
||||
"link": null
|
||||
},
|
||||
"annotations": {
|
||||
"bold": false,
|
||||
"italic": false,
|
||||
"strikethrough": false,
|
||||
"underline": false,
|
||||
"code": false,
|
||||
"color": "default"
|
||||
},
|
||||
"plain_text": "TEST_DB",
|
||||
"href": null
|
||||
}
|
||||
],
|
||||
"description": [],
|
||||
"is_inline": false,
|
||||
"properties": {
|
||||
"Tags": {
|
||||
"id": "%40~Tp",
|
||||
"name": "Tags",
|
||||
"type": "multi_select",
|
||||
"multi_select": {
|
||||
"options": []
|
||||
}
|
||||
},
|
||||
"Name": {
|
||||
"id": "title",
|
||||
"name": "Name",
|
||||
"type": "title",
|
||||
"title": {}
|
||||
}
|
||||
},
|
||||
"parent": {
|
||||
"type": "page_id",
|
||||
"page_id": "cc3d2b3c-f31a-4773-ab39-17a60c54567a"
|
||||
},
|
||||
"url": "https://www.notion.so/138fb9cb4cf0804c8663d8ecdd5e692f",
|
||||
"public_url": null,
|
||||
"archived": false,
|
||||
"in_trash": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "08dad8e3-abcc-42d1-8ad3-c026644d1280",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
object: 'page',
|
||||
id: '15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3',
|
||||
created_time: '2024-12-13T04:45:00.000Z',
|
||||
last_edited_time: '2024-12-13T04:45:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
cover: null,
|
||||
icon: {
|
||||
type: 'emoji',
|
||||
emoji: '😗',
|
||||
},
|
||||
parent: {
|
||||
type: 'database_id',
|
||||
database_id: '138fb9cb-4cf0-804c-8663-d8ecdd5e692f',
|
||||
},
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
properties: {
|
||||
Tags: {
|
||||
id: '%40~Tp',
|
||||
type: 'multi_select',
|
||||
multi_select: [],
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
type: 'title',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'new name 1',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'new name 1',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
url: 'https://www.notion.so/new-name-1-15bfb9cb4cf081c7aab4c5855b8cb6c3',
|
||||
public_url: null,
|
||||
request_id: '1416702d-daa8-4f8d-9be3-c55fe52486b5',
|
||||
};
|
||||
|
||||
describe('Test NotionV2, databasePage => create', () => {
|
||||
nock('https://api.notion.com')
|
||||
.get('/v1/databases/138fb9cb-4cf0-804c-8663-d8ecdd5e692f')
|
||||
.reply(200, {
|
||||
properties: {
|
||||
Tags: {
|
||||
id: '%40~Tp',
|
||||
name: 'Tags',
|
||||
type: 'multi_select',
|
||||
multi_select: {
|
||||
options: [],
|
||||
},
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
name: 'Name',
|
||||
type: 'title',
|
||||
title: {},
|
||||
},
|
||||
},
|
||||
})
|
||||
.post('/v1/pages', {
|
||||
parent: { database_id: '138fb9cb-4cf0-804c-8663-d8ecdd5e692f' },
|
||||
properties: { Name: { title: [{ text: { content: 'new name 1' } }] } },
|
||||
children: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
paragraph: { text: [{ text: { content: 'new text' } }] },
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
type: 'toggle',
|
||||
toggle: { text: [{ text: { content: 'new toggle' } }] },
|
||||
},
|
||||
],
|
||||
icon: { emoji: '😗' },
|
||||
})
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['create.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "databasePage",
|
||||
"databaseId": {
|
||||
"__rl": true,
|
||||
"value": "138fb9cb-4cf0-804c-8663-d8ecdd5e692f",
|
||||
"mode": "list",
|
||||
"cachedResultName": "TEST_DB",
|
||||
"cachedResultUrl": "https://www.notion.so/138fb9cb4cf0804c8663d8ecdd5e692f"
|
||||
},
|
||||
"title": "new page",
|
||||
"propertiesUi": {
|
||||
"propertyValues": [
|
||||
{
|
||||
"key": "Name|title",
|
||||
"title": "new name 1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"blockUi": {
|
||||
"blockValues": [
|
||||
{
|
||||
"textContent": "new text"
|
||||
},
|
||||
{
|
||||
"type": "toggle",
|
||||
"textContent": "new toggle"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"iconType": "emoji",
|
||||
"icon": "😗"
|
||||
}
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"id": "15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3",
|
||||
"name": "new name 1",
|
||||
"url": "https://www.notion.so/new-name-1-15bfb9cb4cf081c7aab4c5855b8cb6c3",
|
||||
"property_tags": [],
|
||||
"property_name": "new name 1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "5f4f1112-c094-44b6-bc05-005b54190852",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
object: 'page',
|
||||
id: '15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3',
|
||||
created_time: '2024-12-13T04:45:00.000Z',
|
||||
last_edited_time: '2024-12-13T04:45:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
cover: null,
|
||||
icon: {
|
||||
type: 'emoji',
|
||||
emoji: '😗',
|
||||
},
|
||||
parent: {
|
||||
type: 'database_id',
|
||||
database_id: '138fb9cb-4cf0-804c-8663-d8ecdd5e692f',
|
||||
},
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
properties: {
|
||||
Tags: {
|
||||
id: '%40~Tp',
|
||||
type: 'multi_select',
|
||||
multi_select: [],
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
type: 'title',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'new name 1',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'new name 1',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
url: 'https://www.notion.so/new-name-1-15bfb9cb4cf081c7aab4c5855b8cb6c3',
|
||||
public_url: null,
|
||||
request_id: 'c01d3a3e-d9c3-4e48-8d73-077a8503c3ba',
|
||||
};
|
||||
|
||||
describe('Test NotionV2, databasePage => get', () => {
|
||||
nock('https://api.notion.com')
|
||||
.get('/v1/pages/15bfb9cb4cf081c7aab4c5855b8cb6c3')
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['get.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "databasePage",
|
||||
"operation": "get",
|
||||
"pageId": {
|
||||
"__rl": true,
|
||||
"value": "https://www.notion.so/138fb9cb4cf0804c8663d8ecdd5e692f?v=7bcc03614eed4c95a9e6168c040e9c58&p=15bfb9cb4cf081c7aab4c5855b8cb6c3&pm=s",
|
||||
"mode": "url"
|
||||
}
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"id": "15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3",
|
||||
"name": "new name 1",
|
||||
"url": "https://www.notion.so/new-name-1-15bfb9cb4cf081c7aab4c5855b8cb6c3",
|
||||
"property_tags": [],
|
||||
"property_name": "new name 1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "68afba7e-c066-458c-984b-c758ef92463c",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
results: [
|
||||
{
|
||||
object: 'page',
|
||||
id: '15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3',
|
||||
created_time: '2024-12-13T04:45:00.000Z',
|
||||
last_edited_time: '2024-12-13T04:45:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
cover: null,
|
||||
icon: {
|
||||
type: 'emoji',
|
||||
emoji: '😗',
|
||||
},
|
||||
parent: {
|
||||
type: 'database_id',
|
||||
database_id: '138fb9cb-4cf0-804c-8663-d8ecdd5e692f',
|
||||
},
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
properties: {
|
||||
Tags: {
|
||||
id: '%40~Tp',
|
||||
type: 'multi_select',
|
||||
multi_select: [],
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
type: 'title',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'new name 1',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'new name 1',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
url: 'https://www.notion.so/new-name-1-15bfb9cb4cf081c7aab4c5855b8cb6c3',
|
||||
public_url: null,
|
||||
},
|
||||
],
|
||||
has_more: false,
|
||||
};
|
||||
|
||||
describe('Test NotionV2, databasePage => getAll', () => {
|
||||
nock('https://api.notion.com')
|
||||
.post('/v1/databases/138fb9cb-4cf0-804c-8663-d8ecdd5e692f/query', {
|
||||
filter: { or: [{ property: 'Name', title: { contains: 'new' } }] },
|
||||
sorts: [{ direction: 'ascending', property: 'Name' }],
|
||||
})
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['getAll.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,114 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "databasePage",
|
||||
"operation": "getAll",
|
||||
"databaseId": {
|
||||
"__rl": true,
|
||||
"value": "138fb9cb-4cf0-804c-8663-d8ecdd5e692f",
|
||||
"mode": "list",
|
||||
"cachedResultName": "TEST_DB",
|
||||
"cachedResultUrl": "https://www.notion.so/138fb9cb4cf0804c8663d8ecdd5e692f"
|
||||
},
|
||||
"returnAll": true,
|
||||
"filterType": "manual",
|
||||
"filters": {
|
||||
"conditions": [
|
||||
{
|
||||
"key": "Name|title",
|
||||
"condition": "contains",
|
||||
"titleValue": "new"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"sort": {
|
||||
"sortValue": [
|
||||
{
|
||||
"key": "Name|title",
|
||||
"direction": "ascending"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"id": "15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3",
|
||||
"name": "new name 1",
|
||||
"url": "https://www.notion.so/new-name-1-15bfb9cb4cf081c7aab4c5855b8cb6c3",
|
||||
"property_tags": [],
|
||||
"property_name": "new name 1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "c69706eb-f8e8-4fe0-b456-23e482743d1c",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
object: 'page',
|
||||
id: '15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3',
|
||||
created_time: '2024-12-13T04:45:00.000Z',
|
||||
last_edited_time: '2024-12-13T05:21:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
cover: null,
|
||||
icon: {
|
||||
type: 'emoji',
|
||||
emoji: '😗',
|
||||
},
|
||||
parent: {
|
||||
type: 'database_id',
|
||||
database_id: '138fb9cb-4cf0-804c-8663-d8ecdd5e692f',
|
||||
},
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
properties: {
|
||||
Tags: {
|
||||
id: '%40~Tp',
|
||||
type: 'multi_select',
|
||||
multi_select: [],
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
type: 'title',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'Updated Name',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'Updated Name',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
url: 'https://www.notion.so/Updated-Name-15bfb9cb4cf081c7aab4c5855b8cb6c3',
|
||||
public_url: null,
|
||||
request_id: 'a4683091-f165-4f10-92b4-a629b8b1266e',
|
||||
};
|
||||
|
||||
describe('Test NotionV2, databasePage => update', () => {
|
||||
nock('https://api.notion.com')
|
||||
.patch('/v1/pages/15bfb9cb4cf081c7aab4c5855b8cb6c3', {
|
||||
properties: { Name: { title: [{ text: { content: 'Updated Name' } }] } },
|
||||
})
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['update.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "databasePage",
|
||||
"operation": "update",
|
||||
"pageId": {
|
||||
"__rl": true,
|
||||
"value": "https://www.notion.so/new-name-1-15bfb9cb4cf081c7aab4c5855b8cb6c3",
|
||||
"mode": "url"
|
||||
},
|
||||
"propertiesUi": {
|
||||
"propertyValues": [
|
||||
{
|
||||
"key": "Name|title",
|
||||
"title": "Updated Name"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {}
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"id": "15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3",
|
||||
"name": "Updated Name",
|
||||
"url": "https://www.notion.so/Updated-Name-15bfb9cb4cf081c7aab4c5855b8cb6c3",
|
||||
"property_tags": [],
|
||||
"property_name": "Updated Name"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "ab4a62f2-5d45-456a-ac7a-97cf84e78815",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
object: 'page',
|
||||
id: '15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3',
|
||||
created_time: '2024-12-13T04:45:00.000Z',
|
||||
last_edited_time: '2024-12-13T05:52:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
cover: null,
|
||||
icon: {
|
||||
type: 'emoji',
|
||||
emoji: '😗',
|
||||
},
|
||||
parent: {
|
||||
type: 'database_id',
|
||||
database_id: '138fb9cb-4cf0-804c-8663-d8ecdd5e692f',
|
||||
},
|
||||
archived: true,
|
||||
in_trash: true,
|
||||
properties: {
|
||||
Tags: {
|
||||
id: '%40~Tp',
|
||||
type: 'multi_select',
|
||||
multi_select: [],
|
||||
},
|
||||
Name: {
|
||||
id: 'title',
|
||||
type: 'title',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'Updated Name',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'Updated Name',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
url: 'https://www.notion.so/Updated-Name-15bfb9cb4cf081c7aab4c5855b8cb6c3',
|
||||
public_url: null,
|
||||
request_id: 'ce91abaa-261f-43c3-9237-57c0f28af682',
|
||||
};
|
||||
|
||||
describe('Test NotionV2, page => archive', () => {
|
||||
nock('https://api.notion.com')
|
||||
.patch('/v1/pages/15bfb9cb4cf081c7aab4c5855b8cb6c3', { archived: true })
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['archive.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"operation": "archive",
|
||||
"pageId": {
|
||||
"__rl": true,
|
||||
"value": "15bfb9cb4cf081c7aab4c5855b8cb6c3",
|
||||
"mode": "id"
|
||||
}
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"id": "15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3",
|
||||
"name": "Updated Name",
|
||||
"url": "https://www.notion.so/Updated-Name-15bfb9cb4cf081c7aab4c5855b8cb6c3",
|
||||
"property_tags": [],
|
||||
"property_name": "Updated Name"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "aae2fbb6-0277-449a-9f26-d8d3cf53d2c4",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
object: 'page',
|
||||
id: '15bfb9cb-4cf0-812b-b4bc-c85cd00727f8',
|
||||
created_time: '2024-12-13T06:01:00.000Z',
|
||||
last_edited_time: '2024-12-13T06:01:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
cover: null,
|
||||
icon: {
|
||||
type: 'emoji',
|
||||
emoji: '😊',
|
||||
},
|
||||
parent: {
|
||||
type: 'page_id',
|
||||
page_id: '15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3',
|
||||
},
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
properties: {
|
||||
title: {
|
||||
id: 'title',
|
||||
type: 'title',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'Child page',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'Child page',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
url: 'https://www.notion.so/Child-page-15bfb9cb4cf0812bb4bcc85cd00727f8',
|
||||
public_url: null,
|
||||
request_id: 'df28ec00-4361-46af-a3b6-add18c8d1295',
|
||||
};
|
||||
|
||||
describe('Test NotionV2, page => create', () => {
|
||||
nock('https://api.notion.com')
|
||||
.post('/v1/pages', {
|
||||
parent: { page_id: '15bfb9cb4cf081c7aab4c5855b8cb6c3' },
|
||||
properties: { title: [{ text: { content: 'Child page' } }] },
|
||||
children: [
|
||||
{
|
||||
object: 'block',
|
||||
type: 'heading_1',
|
||||
heading_1: { text: [{ type: 'text', text: { content: 'Title' }, annotations: {} }] },
|
||||
},
|
||||
{
|
||||
object: 'block',
|
||||
type: 'paragraph',
|
||||
paragraph: { text: [{ text: { content: 'text' } }] },
|
||||
},
|
||||
],
|
||||
icon: { emoji: '😊' },
|
||||
})
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['create.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,111 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"pageId": {
|
||||
"__rl": true,
|
||||
"value": "15bfb9cb4cf081c7aab4c5855b8cb6c3",
|
||||
"mode": "id",
|
||||
"__regex": "^([0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12})"
|
||||
},
|
||||
"title": "Child page",
|
||||
"blockUi": {
|
||||
"blockValues": [
|
||||
{
|
||||
"type": "heading_1",
|
||||
"richText": true,
|
||||
"text": {
|
||||
"text": [
|
||||
{
|
||||
"text": "Title",
|
||||
"annotationUi": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"textContent": "text"
|
||||
}
|
||||
]
|
||||
},
|
||||
"options": {
|
||||
"icon": "😊"
|
||||
}
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"id": "15bfb9cb-4cf0-812b-b4bc-c85cd00727f8",
|
||||
"name": "Child page",
|
||||
"url": "https://www.notion.so/Child-page-15bfb9cb4cf0812bb4bcc85cd00727f8"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "f8f473ad-4d37-49c4-95f3-187b3a70a6f1",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
results: [
|
||||
{
|
||||
object: 'page',
|
||||
id: '15bfb9cb-4cf0-812b-b4bc-c85cd00727f8',
|
||||
created_time: '2024-12-13T06:01:00.000Z',
|
||||
last_edited_time: '2024-12-13T06:01:00.000Z',
|
||||
created_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
last_edited_by: {
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
},
|
||||
cover: null,
|
||||
icon: {
|
||||
type: 'emoji',
|
||||
emoji: '😊',
|
||||
},
|
||||
parent: {
|
||||
type: 'page_id',
|
||||
page_id: '15bfb9cb-4cf0-81c7-aab4-c5855b8cb6c3',
|
||||
},
|
||||
archived: false,
|
||||
in_trash: false,
|
||||
properties: {
|
||||
title: {
|
||||
id: 'title',
|
||||
type: 'title',
|
||||
title: [
|
||||
{
|
||||
type: 'text',
|
||||
text: {
|
||||
content: 'Child page',
|
||||
link: null,
|
||||
},
|
||||
annotations: {
|
||||
bold: false,
|
||||
italic: false,
|
||||
strikethrough: false,
|
||||
underline: false,
|
||||
code: false,
|
||||
color: 'default',
|
||||
},
|
||||
plain_text: 'Child page',
|
||||
href: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
url: 'https://www.notion.so/Child-page-15bfb9cb4cf0812bb4bcc85cd00727f8',
|
||||
public_url: null,
|
||||
},
|
||||
],
|
||||
has_more: false,
|
||||
};
|
||||
|
||||
describe('Test NotionV2, page => search', () => {
|
||||
nock('https://api.notion.com')
|
||||
.post('/v1/search', {
|
||||
query: 'child',
|
||||
filter: { property: 'object', value: 'page' },
|
||||
sort: { direction: 'ascending', timestamp: 'last_edited_time' },
|
||||
})
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['search.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,97 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"operation": "search",
|
||||
"text": "child",
|
||||
"returnAll": true,
|
||||
"options": {
|
||||
"filter": {
|
||||
"filters": {
|
||||
"value": "page"
|
||||
}
|
||||
},
|
||||
"sort": {
|
||||
"sortValue": {
|
||||
"direction": "ascending"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"id": "15bfb9cb-4cf0-812b-b4bc-c85cd00727f8",
|
||||
"name": "Child page",
|
||||
"url": "https://www.notion.so/Child-page-15bfb9cb4cf0812bb4bcc85cd00727f8"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "75e271ec-4d76-4094-b283-9a3f61a0c111",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
object: 'user',
|
||||
id: '34a945c6-de97-4efc-90d6-6d7cc14a6583',
|
||||
name: 'second',
|
||||
avatar_url: null,
|
||||
type: 'bot',
|
||||
bot: {},
|
||||
request_id: 'ad2a00c0-fa6a-4a14-bf9a-68e1715b51a1',
|
||||
};
|
||||
|
||||
describe('Test NotionV2, user => get', () => {
|
||||
nock('https://api.notion.com')
|
||||
.get('/v1/users/34a945c6-de97-4efc-90d6-6d7cc14a6583')
|
||||
.reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['get.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,88 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "user",
|
||||
"userId": "34a945c6-de97-4efc-90d6-6d7cc14a6583"
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"object": "user",
|
||||
"id": "34a945c6-de97-4efc-90d6-6d7cc14a6583",
|
||||
"name": "second",
|
||||
"avatar_url": null,
|
||||
"type": "bot",
|
||||
"bot": {},
|
||||
"request_id": "ad2a00c0-fa6a-4a14-bf9a-68e1715b51a1"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "d654cac7-21b8-4d6e-99ce-c5c980d9f49d",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
import { NodeTestHarness } from '@nodes-testing/node-test-harness';
|
||||
import nock from 'nock';
|
||||
|
||||
const API_RESPONSE = {
|
||||
results: [
|
||||
{
|
||||
object: 'user',
|
||||
id: 'f215e49c-4677-40c0-9adc-87440d341324',
|
||||
name: 'n8n-test',
|
||||
avatar_url: null,
|
||||
type: 'bot',
|
||||
bot: {
|
||||
owner: {
|
||||
type: 'workspace',
|
||||
workspace: true,
|
||||
},
|
||||
workspace_name: "Michael Kret's Notion",
|
||||
},
|
||||
},
|
||||
{
|
||||
object: 'user',
|
||||
id: '34a945c6-de97-4efc-90d6-6d7cc14a6583',
|
||||
name: 'second',
|
||||
avatar_url: null,
|
||||
type: 'bot',
|
||||
bot: {},
|
||||
},
|
||||
{
|
||||
object: 'user',
|
||||
id: '2598a5de-49b3-4acd-adad-20f6b18c9fbe',
|
||||
name: 'DryMerge',
|
||||
avatar_url:
|
||||
'https://s3-us-west-2.amazonaws.com/public.notion-static.com/e67863a3-a867-4355-a602-c9830dbb1828/Primary_(recommended).jpg',
|
||||
type: 'bot',
|
||||
bot: {},
|
||||
},
|
||||
],
|
||||
has_more: false,
|
||||
};
|
||||
|
||||
describe('Test NotionV2, user => getAll', () => {
|
||||
nock('https://api.notion.com').get('/v1/users').reply(200, API_RESPONSE);
|
||||
|
||||
new NodeTestHarness().setupTests({
|
||||
workflowFiles: ['getAll.workflow.json'],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,104 @@
|
||||
{
|
||||
"name": "tests notion",
|
||||
"nodes": [
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "4260fdbd-e92f-4712-8114-38b85f8289ea",
|
||||
"name": "When clicking ‘Execute workflow’",
|
||||
"type": "n8n-nodes-base.manualTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [820, 360]
|
||||
},
|
||||
{
|
||||
"parameters": {
|
||||
"resource": "user",
|
||||
"operation": "getAll",
|
||||
"limit": 2
|
||||
},
|
||||
"id": "5ab80e6a-c9c4-4cc5-9332-2fc7a3f8ae24",
|
||||
"name": "Notion",
|
||||
"type": "n8n-nodes-base.notion",
|
||||
"typeVersion": 2.2,
|
||||
"position": [1040, 360],
|
||||
"credentials": {
|
||||
"notionApi": {
|
||||
"id": "CiZXWkDmjiZzpcL1",
|
||||
"name": "Notion account"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"parameters": {},
|
||||
"id": "a664f506-72a5-4e50-80b4-97ed2e6eb334",
|
||||
"name": "No Operation, do nothing",
|
||||
"type": "n8n-nodes-base.noOp",
|
||||
"typeVersion": 1,
|
||||
"position": [1260, 360]
|
||||
}
|
||||
],
|
||||
"pinData": {
|
||||
"No Operation, do nothing": [
|
||||
{
|
||||
"json": {
|
||||
"object": "user",
|
||||
"id": "f215e49c-4677-40c0-9adc-87440d341324",
|
||||
"name": "n8n-test",
|
||||
"avatar_url": null,
|
||||
"type": "bot",
|
||||
"bot": {
|
||||
"owner": {
|
||||
"type": "workspace",
|
||||
"workspace": true
|
||||
},
|
||||
"workspace_name": "Michael Kret's Notion"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"json": {
|
||||
"object": "user",
|
||||
"id": "34a945c6-de97-4efc-90d6-6d7cc14a6583",
|
||||
"name": "second",
|
||||
"avatar_url": null,
|
||||
"type": "bot",
|
||||
"bot": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"connections": {
|
||||
"When clicking ‘Execute workflow’": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Notion",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Notion": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "No Operation, do nothing",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"versionId": "702bd2aa-53d0-4c82-bbc2-a95a153953b0",
|
||||
"meta": {
|
||||
"templateCredsSetupCompleted": true,
|
||||
"instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd"
|
||||
},
|
||||
"id": "Ucav6QC99JNMCkd3",
|
||||
"tags": []
|
||||
}
|
||||
@@ -0,0 +1,626 @@
|
||||
import moment from 'moment-timezone';
|
||||
import type {
|
||||
IExecuteFunctions,
|
||||
IDataObject,
|
||||
ILoadOptionsFunctions,
|
||||
INodeExecutionData,
|
||||
INodePropertyOptions,
|
||||
INodeType,
|
||||
INodeTypeBaseDescription,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import { versionDescription } from './VersionDescription';
|
||||
import type { SortData } from '../shared/GenericFunctions';
|
||||
import {
|
||||
extractDatabaseId,
|
||||
extractDatabaseMentionRLC,
|
||||
extractPageId,
|
||||
formatBlocks,
|
||||
formatTitle,
|
||||
getBlockTypesOptions,
|
||||
mapFilters,
|
||||
mapProperties,
|
||||
mapSorting,
|
||||
notionApiRequest,
|
||||
notionApiRequestAllItems,
|
||||
simplifyObjects,
|
||||
} from '../shared/GenericFunctions';
|
||||
import { listSearch } from '../shared/methods';
|
||||
|
||||
export class NotionV1 implements INodeType {
|
||||
description: INodeTypeDescription;
|
||||
|
||||
constructor(baseDescription: INodeTypeBaseDescription) {
|
||||
this.description = {
|
||||
...baseDescription,
|
||||
...versionDescription,
|
||||
};
|
||||
}
|
||||
|
||||
methods = {
|
||||
listSearch,
|
||||
loadOptions: {
|
||||
async getDatabaseProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const databaseId = this.getCurrentNodeParameter('databaseId', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const { properties } = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
for (const key of Object.keys(properties as IDataObject)) {
|
||||
//remove parameters that cannot be set from the API.
|
||||
if (
|
||||
![
|
||||
'created_time',
|
||||
'last_edited_time',
|
||||
'created_by',
|
||||
'last_edited_by',
|
||||
'formula',
|
||||
'files',
|
||||
'rollup',
|
||||
].includes(properties[key].type as string)
|
||||
) {
|
||||
returnData.push({
|
||||
name: `${key} - (${properties[key].type})`,
|
||||
value: `${key}|${properties[key].type}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
returnData.sort((a, b) => {
|
||||
if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return returnData;
|
||||
},
|
||||
async getFilterProperties(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const databaseId = this.getCurrentNodeParameter('databaseId', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const { properties } = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
for (const key of Object.keys(properties as IDataObject)) {
|
||||
returnData.push({
|
||||
name: `${key} - (${properties[key].type})`,
|
||||
value: `${key}|${properties[key].type}`,
|
||||
});
|
||||
}
|
||||
returnData.sort((a, b) => {
|
||||
if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return returnData;
|
||||
},
|
||||
async getBlockTypes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
return getBlockTypesOptions();
|
||||
},
|
||||
async getPropertySelectValues(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const [name, type] = (this.getCurrentNodeParameter('&key') as string).split('|');
|
||||
const databaseId = this.getCurrentNodeParameter('databaseId', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const resource = this.getCurrentNodeParameter('resource') as string;
|
||||
const operation = this.getCurrentNodeParameter('operation') as string;
|
||||
const { properties } = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
if (resource === 'databasePage') {
|
||||
if (['multi_select', 'select'].includes(type) && operation === 'getAll') {
|
||||
return properties[name][type].options.map((option: IDataObject) => ({
|
||||
name: option.name,
|
||||
value: option.name,
|
||||
}));
|
||||
} else if (['multi_select'].includes(type) && ['create', 'update'].includes(operation)) {
|
||||
return properties[name][type].options.map((option: IDataObject) => ({
|
||||
name: option.name,
|
||||
value: option.name,
|
||||
}));
|
||||
}
|
||||
}
|
||||
return properties[name][type].options.map((option: IDataObject) => ({
|
||||
name: option.name,
|
||||
value: option.id,
|
||||
}));
|
||||
},
|
||||
async getUsers(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const users = await notionApiRequestAllItems.call(this, 'results', 'GET', '/users');
|
||||
for (const user of users) {
|
||||
if (user.type === 'person') {
|
||||
returnData.push({
|
||||
name: user.name,
|
||||
value: user.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
async getDatabaseIdFromPage(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const pageId = extractPageId(
|
||||
this.getCurrentNodeParameter('pageId', { extractValue: true }) as string,
|
||||
);
|
||||
const {
|
||||
parent: { database_id: databaseId },
|
||||
} = await notionApiRequest.call(this, 'GET', `/pages/${pageId}`);
|
||||
const { properties } = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
for (const key of Object.keys(properties as IDataObject)) {
|
||||
//remove parameters that cannot be set from the API.
|
||||
if (
|
||||
![
|
||||
'created_time',
|
||||
'last_edited_time',
|
||||
'created_by',
|
||||
'last_edited_by',
|
||||
'formula',
|
||||
'files',
|
||||
].includes(properties[key].type as string)
|
||||
) {
|
||||
returnData.push({
|
||||
name: `${key} - (${properties[key].type})`,
|
||||
value: `${key}|${properties[key].type}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
returnData.sort((a, b) => {
|
||||
if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return returnData;
|
||||
},
|
||||
|
||||
async getDatabaseOptionsFromPage(
|
||||
this: ILoadOptionsFunctions,
|
||||
): Promise<INodePropertyOptions[]> {
|
||||
const pageId = extractPageId(
|
||||
this.getCurrentNodeParameter('pageId', { extractValue: true }) as string,
|
||||
);
|
||||
const [name, type] = (this.getCurrentNodeParameter('&key') as string).split('|');
|
||||
const {
|
||||
parent: { database_id: databaseId },
|
||||
} = await notionApiRequest.call(this, 'GET', `/pages/${pageId}`);
|
||||
const { properties } = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
return properties[name][type].options.map((option: IDataObject) => ({
|
||||
name: option.name,
|
||||
value: option.id,
|
||||
}));
|
||||
},
|
||||
|
||||
// Get all the timezones to display them to user so that they can
|
||||
// select them easily
|
||||
async getTimezones(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
for (const timezone of moment.tz.names()) {
|
||||
const timezoneName = timezone;
|
||||
const timezoneId = timezone;
|
||||
returnData.push({
|
||||
name: timezoneName,
|
||||
value: timezoneId,
|
||||
});
|
||||
}
|
||||
returnData.unshift({
|
||||
name: 'Default',
|
||||
value: 'default',
|
||||
description: 'Timezone set in n8n',
|
||||
});
|
||||
return returnData;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const returnData: INodeExecutionData[] = [];
|
||||
const length = items.length;
|
||||
let responseData;
|
||||
const qs: IDataObject = {};
|
||||
const timezone = this.getTimezone();
|
||||
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
|
||||
if (resource === 'block') {
|
||||
if (operation === 'append') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const blockId = extractPageId(
|
||||
this.getNodeParameter('blockId', i, '', { extractValue: true }) as string,
|
||||
);
|
||||
const blockValues = this.getNodeParameter('blockUi.blockValues', i, []) as IDataObject[];
|
||||
extractDatabaseMentionRLC(blockValues);
|
||||
const body: IDataObject = {
|
||||
children: formatBlocks(blockValues),
|
||||
};
|
||||
const block = await notionApiRequest.call(
|
||||
this,
|
||||
'PATCH',
|
||||
`/blocks/${blockId}/children`,
|
||||
body,
|
||||
);
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(block as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'getAll') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const blockId = extractPageId(
|
||||
this.getNodeParameter('blockId', i, '', { extractValue: true }) as string,
|
||||
);
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
if (returnAll) {
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'GET',
|
||||
`/blocks/${blockId}/children`,
|
||||
{},
|
||||
);
|
||||
} else {
|
||||
qs.page_size = this.getNodeParameter('limit', i);
|
||||
responseData = await notionApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/blocks/${blockId}/children`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
responseData = responseData.results;
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === 'database') {
|
||||
if (operation === 'get') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const databaseId = extractDatabaseId(
|
||||
this.getNodeParameter('databaseId', i, '', { extractValue: true }) as string,
|
||||
);
|
||||
responseData = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'getAll') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const body: IDataObject = {
|
||||
filter: { property: 'object', value: 'database' },
|
||||
};
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
if (returnAll) {
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'POST',
|
||||
'/search',
|
||||
body,
|
||||
);
|
||||
} else {
|
||||
body.page_size = this.getNodeParameter('limit', i);
|
||||
responseData = await notionApiRequest.call(this, 'POST', '/search', body);
|
||||
responseData = responseData.results;
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === 'databasePage') {
|
||||
if (operation === 'create') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
|
||||
const body: { [key: string]: any } = {
|
||||
parent: {},
|
||||
properties: {},
|
||||
};
|
||||
body.parent.database_id = this.getNodeParameter('databaseId', i, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const properties = this.getNodeParameter(
|
||||
'propertiesUi.propertyValues',
|
||||
i,
|
||||
[],
|
||||
) as IDataObject[];
|
||||
if (properties.length !== 0) {
|
||||
body.properties = mapProperties.call(this, properties, timezone) as IDataObject;
|
||||
}
|
||||
const blockValues = this.getNodeParameter('blockUi.blockValues', i, []) as IDataObject[];
|
||||
extractDatabaseMentionRLC(blockValues);
|
||||
body.children = formatBlocks(blockValues);
|
||||
responseData = await notionApiRequest.call(this, 'POST', '/pages', body);
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, false, 1);
|
||||
}
|
||||
|
||||
const options = this.getNodeParameter('options', i);
|
||||
if (options.icon) {
|
||||
if (options.iconType && options.iconType === 'file') {
|
||||
body.icon = { external: { url: options.icon } };
|
||||
} else {
|
||||
body.icon = { emoji: options.icon };
|
||||
}
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'getAll') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const simple = this.getNodeParameter('simple', 0) as boolean;
|
||||
const databaseId = this.getNodeParameter('databaseId', i, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const filters = this.getNodeParameter('options.filter', i, {}) as IDataObject;
|
||||
const sort = this.getNodeParameter('options.sort.sortValue', i, []) as SortData[];
|
||||
const body: IDataObject = {
|
||||
filter: {},
|
||||
};
|
||||
if (filters.singleCondition) {
|
||||
body.filter = mapFilters([filters.singleCondition] as IDataObject[], timezone);
|
||||
}
|
||||
if (filters.multipleCondition) {
|
||||
const { or, and } = (filters.multipleCondition as IDataObject).condition as IDataObject;
|
||||
if (Array.isArray(or) && or.length !== 0) {
|
||||
Object.assign(body.filter!, {
|
||||
or: (or as IDataObject[]).map((data) => mapFilters([data], timezone)),
|
||||
});
|
||||
}
|
||||
if (Array.isArray(and) && and.length !== 0) {
|
||||
Object.assign(body.filter!, {
|
||||
and: (and as IDataObject[]).map((data) => mapFilters([data], timezone)),
|
||||
});
|
||||
}
|
||||
}
|
||||
if (!Object.keys(body.filter as IDataObject).length) {
|
||||
delete body.filter;
|
||||
}
|
||||
if (sort) {
|
||||
body.sorts = mapSorting(sort);
|
||||
}
|
||||
if (returnAll) {
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'POST',
|
||||
`/databases/${databaseId}/query`,
|
||||
body,
|
||||
{},
|
||||
);
|
||||
} else {
|
||||
body.page_size = this.getNodeParameter('limit', i);
|
||||
responseData = await notionApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
`/databases/${databaseId}/query`,
|
||||
body,
|
||||
qs,
|
||||
);
|
||||
responseData = responseData.results;
|
||||
}
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, false, 1);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'update') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const pageId = extractPageId(
|
||||
this.getNodeParameter('pageId', i, '', { extractValue: true }) as string,
|
||||
);
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
const properties = this.getNodeParameter(
|
||||
'propertiesUi.propertyValues',
|
||||
i,
|
||||
[],
|
||||
) as IDataObject[];
|
||||
|
||||
const body: { [key: string]: any } = {
|
||||
properties: {},
|
||||
};
|
||||
if (properties.length !== 0) {
|
||||
body.properties = mapProperties.call(this, properties, timezone) as IDataObject;
|
||||
}
|
||||
responseData = await notionApiRequest.call(this, 'PATCH', `/pages/${pageId}`, body);
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, false, 1);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === 'user') {
|
||||
if (operation === 'get') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const userId = this.getNodeParameter('userId', i) as string;
|
||||
responseData = await notionApiRequest.call(this, 'GET', `/users/${userId}`);
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
if (operation === 'getAll') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
if (returnAll) {
|
||||
responseData = await notionApiRequestAllItems.call(this, 'results', 'GET', '/users');
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', i);
|
||||
responseData = await notionApiRequestAllItems.call(this, 'results', 'GET', '/users');
|
||||
responseData = responseData.splice(0, qs.limit);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === 'page') {
|
||||
if (operation === 'create') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
|
||||
const body: { [key: string]: any } = {
|
||||
parent: {},
|
||||
properties: {},
|
||||
};
|
||||
body.parent.page_id = extractPageId(
|
||||
this.getNodeParameter('pageId', i, '', { extractValue: true }) as string,
|
||||
);
|
||||
body.properties = formatTitle(this.getNodeParameter('title', i) as string);
|
||||
const blockValues = this.getNodeParameter('blockUi.blockValues', i, []) as IDataObject[];
|
||||
extractDatabaseMentionRLC(blockValues);
|
||||
body.children = formatBlocks(blockValues);
|
||||
responseData = await notionApiRequest.call(this, 'POST', '/pages', body);
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, false, 1);
|
||||
}
|
||||
|
||||
const options = this.getNodeParameter('options', i);
|
||||
if (options.icon) {
|
||||
if (options.iconType && options.iconType === 'file') {
|
||||
body.icon = { external: { url: options.icon } };
|
||||
} else {
|
||||
body.icon = { emoji: options.icon };
|
||||
}
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'get') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const pageId = extractPageId(this.getNodeParameter('pageId', i) as string);
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
responseData = await notionApiRequest.call(this, 'GET', `/pages/${pageId}`);
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, false, 1);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'search') {
|
||||
for (let i = 0; i < length; i++) {
|
||||
const text = this.getNodeParameter('text', i) as string;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
const body: IDataObject = {};
|
||||
|
||||
if (text) {
|
||||
body.query = text;
|
||||
}
|
||||
|
||||
if (options.filter) {
|
||||
const filter = ((options.filter as IDataObject)?.filters as IDataObject[]) || [];
|
||||
body.filter = filter;
|
||||
}
|
||||
|
||||
if (options.sort) {
|
||||
const sort = ((options.sort as IDataObject)?.sortValue as IDataObject) || {};
|
||||
body.sort = sort;
|
||||
}
|
||||
if (returnAll) {
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'POST',
|
||||
'/search',
|
||||
body,
|
||||
);
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', i);
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'POST',
|
||||
'/search',
|
||||
body,
|
||||
);
|
||||
responseData = responseData.splice(0, qs.limit);
|
||||
}
|
||||
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, false, 1);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData.push(...executionData);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [returnData];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/* eslint-disable n8n-nodes-base/node-filename-against-convention */
|
||||
import { NodeConnectionTypes, type INodeTypeDescription } from 'n8n-workflow';
|
||||
|
||||
import { blockFields, blockOperations } from '../shared/descriptions/BlockDescription';
|
||||
import { databaseFields, databaseOperations } from '../shared/descriptions/DatabaseDescription';
|
||||
import {
|
||||
databasePageFields,
|
||||
databasePageOperations,
|
||||
} from '../shared/descriptions/DatabasePageDescription';
|
||||
import { pageFields, pageOperations } from '../shared/descriptions/PageDescription';
|
||||
import { userFields, userOperations } from '../shared/descriptions/UserDescription';
|
||||
|
||||
export const versionDescription: INodeTypeDescription = {
|
||||
displayName: 'Notion',
|
||||
name: 'notion',
|
||||
icon: 'file:notion.svg',
|
||||
group: ['output'],
|
||||
version: 1,
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume Notion API',
|
||||
defaults: {
|
||||
name: 'Notion',
|
||||
},
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
credentials: [
|
||||
{
|
||||
name: 'notionApi',
|
||||
required: true,
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// authentication: [
|
||||
// 'apiKey',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
},
|
||||
// {
|
||||
// name: 'notionOAuth2Api',
|
||||
// required: true,
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// authentication: [
|
||||
// 'oAuth2',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
],
|
||||
properties: [
|
||||
// {
|
||||
// displayName: 'Authentication',
|
||||
// name: 'authentication',
|
||||
// type: 'options',
|
||||
// options: [
|
||||
// {
|
||||
// name: 'API Key',
|
||||
// value: 'apiKey',
|
||||
// },
|
||||
// {
|
||||
// name: 'OAuth2',
|
||||
// value: 'oAuth2',
|
||||
// },
|
||||
// ],
|
||||
// default: 'apiKey',
|
||||
// description: 'The resource to operate on.',
|
||||
// },
|
||||
{
|
||||
displayName:
|
||||
'In Notion, make sure to <a href="https://www.notion.so/help/add-and-manage-connections-with-the-api" target="_blank">add your connection</a> to the pages you want to access.',
|
||||
name: 'notionNotice',
|
||||
type: 'notice',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Block',
|
||||
value: 'block',
|
||||
},
|
||||
{
|
||||
name: 'Database',
|
||||
value: 'database',
|
||||
},
|
||||
{
|
||||
name: 'Database Page',
|
||||
value: 'databasePage',
|
||||
},
|
||||
{
|
||||
name: 'Page',
|
||||
value: 'page',
|
||||
},
|
||||
{
|
||||
name: 'User',
|
||||
value: 'user',
|
||||
},
|
||||
],
|
||||
default: 'page',
|
||||
},
|
||||
...blockOperations,
|
||||
...blockFields,
|
||||
...databaseOperations,
|
||||
...databaseFields,
|
||||
...databasePageOperations,
|
||||
...databasePageFields,
|
||||
...pageOperations,
|
||||
...pageFields,
|
||||
...userOperations,
|
||||
...userFields,
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1,776 @@
|
||||
import type {
|
||||
IExecuteFunctions,
|
||||
IDataObject,
|
||||
INodeExecutionData,
|
||||
INodeType,
|
||||
INodeTypeBaseDescription,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
import { jsonParse, NodeApiError } from 'n8n-workflow';
|
||||
|
||||
import { loadOptions } from './methods';
|
||||
import { versionDescription } from './VersionDescription';
|
||||
import type { SortData, FileRecord } from '../shared/GenericFunctions';
|
||||
import {
|
||||
downloadFiles,
|
||||
extractBlockId,
|
||||
extractDatabaseId,
|
||||
extractDatabaseMentionRLC,
|
||||
getPageId,
|
||||
formatBlocks,
|
||||
formatTitle,
|
||||
mapFilters,
|
||||
mapProperties,
|
||||
mapSorting,
|
||||
notionApiRequest,
|
||||
notionApiRequestAllItems,
|
||||
notionApiRequestGetBlockChildrens,
|
||||
prepareNotionError,
|
||||
simplifyBlocksOutput,
|
||||
simplifyObjects,
|
||||
validateJSON,
|
||||
} from '../shared/GenericFunctions';
|
||||
import { listSearch } from '../shared/methods';
|
||||
|
||||
export class NotionV2 implements INodeType {
|
||||
description: INodeTypeDescription;
|
||||
|
||||
constructor(baseDescription: INodeTypeBaseDescription) {
|
||||
this.description = {
|
||||
...baseDescription,
|
||||
...versionDescription,
|
||||
};
|
||||
}
|
||||
|
||||
methods = { listSearch, loadOptions };
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
const items = this.getInputData();
|
||||
const nodeVersion = this.getNode().typeVersion;
|
||||
const resource = this.getNodeParameter('resource', 0);
|
||||
const operation = this.getNodeParameter('operation', 0);
|
||||
|
||||
const itemsLength = items.length;
|
||||
const timezone = this.getTimezone();
|
||||
const qs: IDataObject = {};
|
||||
|
||||
let returnData: INodeExecutionData[] = [];
|
||||
let responseData;
|
||||
let download = false;
|
||||
|
||||
if (resource === 'block') {
|
||||
if (operation === 'append') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const blockId = extractBlockId.call(this, nodeVersion, i);
|
||||
const blockValues = this.getNodeParameter(
|
||||
'blockUi.blockValues',
|
||||
i,
|
||||
[],
|
||||
) as IDataObject[];
|
||||
extractDatabaseMentionRLC(blockValues);
|
||||
const body: IDataObject = {
|
||||
children: formatBlocks(blockValues),
|
||||
};
|
||||
const block = await notionApiRequest.call(
|
||||
this,
|
||||
'PATCH',
|
||||
`/blocks/${blockId}/children`,
|
||||
body,
|
||||
);
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(block as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'getAll') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const blockId = extractBlockId.call(this, nodeVersion, i);
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const fetchNestedBlocks = this.getNodeParameter('fetchNestedBlocks', i) as boolean;
|
||||
|
||||
if (returnAll) {
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'GET',
|
||||
`/blocks/${blockId}/children`,
|
||||
{},
|
||||
);
|
||||
|
||||
if (fetchNestedBlocks) {
|
||||
responseData = await notionApiRequestGetBlockChildrens.call(this, responseData);
|
||||
}
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', i);
|
||||
qs.page_size = limit;
|
||||
responseData = await notionApiRequest.call(
|
||||
this,
|
||||
'GET',
|
||||
`/blocks/${blockId}/children`,
|
||||
{},
|
||||
qs,
|
||||
);
|
||||
const results = responseData.results;
|
||||
|
||||
if (fetchNestedBlocks) {
|
||||
responseData = await notionApiRequestGetBlockChildrens.call(
|
||||
this,
|
||||
results,
|
||||
[],
|
||||
limit,
|
||||
);
|
||||
} else {
|
||||
responseData = results;
|
||||
}
|
||||
}
|
||||
|
||||
responseData = responseData.map((_data: IDataObject) => ({
|
||||
object: _data.object,
|
||||
parent_id: blockId,
|
||||
..._data,
|
||||
}));
|
||||
|
||||
if (nodeVersion > 2) {
|
||||
const simplifyOutput = this.getNodeParameter('simplifyOutput', i) as boolean;
|
||||
|
||||
if (simplifyOutput) {
|
||||
responseData = simplifyBlocksOutput(responseData, blockId);
|
||||
}
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === 'database') {
|
||||
if (operation === 'get') {
|
||||
const simple = this.getNodeParameter('simple', 0) as boolean;
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const databaseId = extractDatabaseId(
|
||||
this.getNodeParameter('databaseId', i, '', { extractValue: true }) as string,
|
||||
);
|
||||
responseData = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, download)[0];
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'getAll') {
|
||||
const simple = this.getNodeParameter('simple', 0) as boolean;
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const body: IDataObject = {
|
||||
filter: { property: 'object', value: 'database' },
|
||||
};
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
if (returnAll) {
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'POST',
|
||||
'/search',
|
||||
body,
|
||||
);
|
||||
} else {
|
||||
body.page_size = this.getNodeParameter('limit', i);
|
||||
responseData = await notionApiRequest.call(this, 'POST', '/search', body);
|
||||
responseData = responseData.results;
|
||||
}
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, download);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'search') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const text = this.getNodeParameter('text', i) as string;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
const body: IDataObject = {
|
||||
filter: {
|
||||
property: 'object',
|
||||
value: 'database',
|
||||
},
|
||||
};
|
||||
|
||||
if (text) {
|
||||
body.query = text;
|
||||
}
|
||||
if (options.sort) {
|
||||
const sort = ((options.sort as IDataObject)?.sortValue as IDataObject) || {};
|
||||
body.sort = sort;
|
||||
}
|
||||
if (returnAll) {
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'POST',
|
||||
'/search',
|
||||
body,
|
||||
);
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', i);
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'POST',
|
||||
'/search',
|
||||
body,
|
||||
);
|
||||
responseData = responseData.splice(0, qs.limit);
|
||||
}
|
||||
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, download);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === 'databasePage') {
|
||||
if (operation === 'create') {
|
||||
const databaseId = this.getNodeParameter('databaseId', 0, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const { properties } = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
let titleKey = '';
|
||||
for (const key of Object.keys(properties as IDataObject)) {
|
||||
if (properties[key].type === 'title') {
|
||||
titleKey = key;
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const title = this.getNodeParameter('title', i) as string;
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
|
||||
const body: { [key: string]: any } = {
|
||||
parent: {},
|
||||
properties: {},
|
||||
};
|
||||
if (title !== '') {
|
||||
body.properties[titleKey] = {
|
||||
title: [
|
||||
{
|
||||
text: {
|
||||
content: title,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
body.parent.database_id = this.getNodeParameter('databaseId', i, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const propertiesValues = this.getNodeParameter(
|
||||
'propertiesUi.propertyValues',
|
||||
i,
|
||||
[],
|
||||
) as IDataObject[];
|
||||
if (propertiesValues.length !== 0) {
|
||||
body.properties = Object.assign(
|
||||
body.properties,
|
||||
mapProperties.call(this, propertiesValues, timezone, 2) as IDataObject,
|
||||
);
|
||||
}
|
||||
const blockValues = this.getNodeParameter(
|
||||
'blockUi.blockValues',
|
||||
i,
|
||||
[],
|
||||
) as IDataObject[];
|
||||
extractDatabaseMentionRLC(blockValues);
|
||||
body.children = formatBlocks(blockValues);
|
||||
|
||||
const options = this.getNodeParameter('options', i);
|
||||
if (options.icon) {
|
||||
if (options.iconType && options.iconType === 'file') {
|
||||
body.icon = { external: { url: options.icon } };
|
||||
} else {
|
||||
body.icon = { emoji: options.icon };
|
||||
}
|
||||
}
|
||||
|
||||
responseData = await notionApiRequest.call(this, 'POST', '/pages', body);
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'get') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const pageId = getPageId.call(this, i);
|
||||
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
responseData = await notionApiRequest.call(this, 'GET', `/pages/${pageId}`);
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, download);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'getAll') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
download = this.getNodeParameter('options.downloadFiles', 0, false) as boolean;
|
||||
const simple = this.getNodeParameter('simple', 0) as boolean;
|
||||
const databaseId = this.getNodeParameter('databaseId', i, '', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const filterType = this.getNodeParameter('filterType', 0) as string;
|
||||
const conditions = this.getNodeParameter('filters.conditions', i, []) as IDataObject[];
|
||||
const sort = this.getNodeParameter('options.sort.sortValue', i, []) as IDataObject[];
|
||||
const body: IDataObject = {
|
||||
filter: {},
|
||||
};
|
||||
|
||||
if (filterType === 'manual') {
|
||||
const matchType = this.getNodeParameter('matchType', 0) as string;
|
||||
if (matchType === 'anyFilter') {
|
||||
Object.assign(body.filter!, {
|
||||
or: conditions.map((data) => mapFilters([data], timezone)),
|
||||
});
|
||||
} else if (matchType === 'allFilters') {
|
||||
Object.assign(body.filter!, {
|
||||
and: conditions.map((data) => mapFilters([data], timezone)),
|
||||
});
|
||||
}
|
||||
} else if (filterType === 'json') {
|
||||
const filterJson = this.getNodeParameter('filterJson', i) as string;
|
||||
if (validateJSON(filterJson) !== undefined) {
|
||||
body.filter = jsonParse(filterJson);
|
||||
} else {
|
||||
throw new NodeApiError(
|
||||
this.getNode(),
|
||||
{
|
||||
message: 'Filters (JSON) must be a valid json',
|
||||
},
|
||||
{ itemIndex: i },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (!Object.keys(body.filter as IDataObject).length) {
|
||||
delete body.filter;
|
||||
}
|
||||
if (sort) {
|
||||
body.sorts = mapSorting(sort as SortData[]);
|
||||
}
|
||||
if (returnAll) {
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'POST',
|
||||
`/databases/${databaseId}/query`,
|
||||
body,
|
||||
{},
|
||||
);
|
||||
} else {
|
||||
body.page_size = this.getNodeParameter('limit', i);
|
||||
responseData = await notionApiRequest.call(
|
||||
this,
|
||||
'POST',
|
||||
`/databases/${databaseId}/query`,
|
||||
body,
|
||||
qs,
|
||||
);
|
||||
responseData = responseData.results;
|
||||
}
|
||||
if (download) {
|
||||
responseData = await downloadFiles.call(this, responseData as FileRecord[], [
|
||||
{ item: i },
|
||||
]);
|
||||
}
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, download);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'update') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const pageId = getPageId.call(this, i);
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
const properties = this.getNodeParameter(
|
||||
'propertiesUi.propertyValues',
|
||||
i,
|
||||
[],
|
||||
) as IDataObject[];
|
||||
|
||||
const body: { [key: string]: any } = {
|
||||
properties: {},
|
||||
};
|
||||
if (properties.length !== 0) {
|
||||
body.properties = mapProperties.call(this, properties, timezone, 2) as IDataObject;
|
||||
}
|
||||
|
||||
const options = this.getNodeParameter('options', i);
|
||||
if (options.icon) {
|
||||
if (options.iconType && options.iconType === 'file') {
|
||||
body.icon = { type: 'external', external: { url: options.icon } };
|
||||
} else {
|
||||
body.icon = { type: 'emoji', emoji: options.icon };
|
||||
}
|
||||
}
|
||||
|
||||
responseData = await notionApiRequest.call(this, 'PATCH', `/pages/${pageId}`, body);
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, false);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === 'user') {
|
||||
if (operation === 'get') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const userId = this.getNodeParameter('userId', i) as string;
|
||||
responseData = await notionApiRequest.call(this, 'GET', `/users/${userId}`);
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (operation === 'getAll') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
if (returnAll) {
|
||||
responseData = await notionApiRequestAllItems.call(this, 'results', 'GET', '/users');
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', i);
|
||||
responseData = await notionApiRequestAllItems.call(this, 'results', 'GET', '/users');
|
||||
responseData = responseData.splice(0, qs.limit);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resource === 'page') {
|
||||
if (operation === 'archive') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const pageId = getPageId.call(this, i);
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
responseData = await notionApiRequest.call(this, 'PATCH', `/pages/${pageId}`, {
|
||||
archived: true,
|
||||
});
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, download);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'create') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
const body: { [key: string]: any } = {
|
||||
parent: {},
|
||||
properties: {},
|
||||
};
|
||||
body.parent.page_id = getPageId.call(this, i);
|
||||
body.properties = formatTitle(this.getNodeParameter('title', i) as string);
|
||||
const blockValues = this.getNodeParameter(
|
||||
'blockUi.blockValues',
|
||||
i,
|
||||
[],
|
||||
) as IDataObject[];
|
||||
extractDatabaseMentionRLC(blockValues);
|
||||
body.children = formatBlocks(blockValues);
|
||||
|
||||
const options = this.getNodeParameter('options', i);
|
||||
if (options.icon) {
|
||||
if (options.iconType && options.iconType === 'file') {
|
||||
body.icon = { external: { url: options.icon } };
|
||||
} else {
|
||||
body.icon = { emoji: options.icon };
|
||||
}
|
||||
}
|
||||
|
||||
responseData = await notionApiRequest.call(this, 'POST', '/pages', body);
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, download);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (operation === 'search') {
|
||||
for (let i = 0; i < itemsLength; i++) {
|
||||
try {
|
||||
const text = this.getNodeParameter('text', i) as string;
|
||||
const options = this.getNodeParameter('options', i);
|
||||
const returnAll = this.getNodeParameter('returnAll', i);
|
||||
const simple = this.getNodeParameter('simple', i) as boolean;
|
||||
const body: IDataObject = {};
|
||||
|
||||
if (text) {
|
||||
body.query = text;
|
||||
}
|
||||
if (options.filter) {
|
||||
const filter = ((options.filter as IDataObject)?.filters as IDataObject[]) || [];
|
||||
body.filter = filter;
|
||||
}
|
||||
if (options.sort) {
|
||||
const sort = ((options.sort as IDataObject)?.sortValue as IDataObject) || {};
|
||||
body.sort = sort;
|
||||
}
|
||||
if (returnAll) {
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'POST',
|
||||
'/search',
|
||||
body,
|
||||
);
|
||||
} else {
|
||||
qs.limit = this.getNodeParameter('limit', i);
|
||||
responseData = await notionApiRequestAllItems.call(
|
||||
this,
|
||||
'results',
|
||||
'POST',
|
||||
'/search',
|
||||
body,
|
||||
);
|
||||
responseData = responseData.splice(0, qs.limit);
|
||||
}
|
||||
|
||||
if (simple) {
|
||||
responseData = simplifyObjects(responseData, download);
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
this.helpers.returnJsonArray(responseData as IDataObject),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
returnData = returnData.concat(executionData);
|
||||
} catch (error) {
|
||||
if (this.continueOnFail()) {
|
||||
returnData.push({
|
||||
json: { error: error.message },
|
||||
pairedItem: { item: i },
|
||||
});
|
||||
} else {
|
||||
throw prepareNotionError(this.getNode(), error, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [returnData];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/* eslint-disable n8n-nodes-base/node-filename-against-convention */
|
||||
import { NodeConnectionTypes, type INodeTypeDescription } from 'n8n-workflow';
|
||||
|
||||
import { blockFields, blockOperations } from '../shared/descriptions/BlockDescription';
|
||||
import { databaseFields, databaseOperations } from '../shared/descriptions/DatabaseDescription';
|
||||
import {
|
||||
databasePageFields,
|
||||
databasePageOperations,
|
||||
} from '../shared/descriptions/DatabasePageDescription';
|
||||
import { pageFields, pageOperations } from '../shared/descriptions/PageDescription';
|
||||
import { userFields, userOperations } from '../shared/descriptions/UserDescription';
|
||||
|
||||
export const versionDescription: INodeTypeDescription = {
|
||||
displayName: 'Notion',
|
||||
name: 'notion',
|
||||
icon: { light: 'file:notion.svg', dark: 'file:notion.dark.svg' },
|
||||
group: ['output'],
|
||||
version: [2, 2.1, 2.2],
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
description: 'Consume Notion API',
|
||||
defaults: {
|
||||
name: 'Notion',
|
||||
},
|
||||
inputs: [NodeConnectionTypes.Main],
|
||||
outputs: [NodeConnectionTypes.Main],
|
||||
usableAsTool: true,
|
||||
credentials: [
|
||||
{
|
||||
name: 'notionApi',
|
||||
required: true,
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// authentication: [
|
||||
// 'apiKey',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
},
|
||||
// {
|
||||
// name: 'notionOAuth2Api',
|
||||
// required: true,
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// authentication: [
|
||||
// 'oAuth2',
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
],
|
||||
properties: [
|
||||
// {
|
||||
// displayName: 'Authentication',
|
||||
// name: 'authentication',
|
||||
// type: 'options',
|
||||
// options: [
|
||||
// {
|
||||
// name: 'API Key',
|
||||
// value: 'apiKey',
|
||||
// },
|
||||
// {
|
||||
// name: 'OAuth2',
|
||||
// value: 'oAuth2',
|
||||
// },
|
||||
// ],
|
||||
// default: 'apiKey',
|
||||
// description: 'The resource to operate on.',
|
||||
// },
|
||||
{
|
||||
displayName:
|
||||
'In Notion, make sure to <a href="https://www.notion.so/help/add-and-manage-connections-with-the-api" target="_blank">add your connection</a> to the pages you want to access.',
|
||||
name: 'notionNotice',
|
||||
type: 'notice',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: '',
|
||||
name: 'Credentials',
|
||||
type: 'credentials',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Resource',
|
||||
name: 'resource',
|
||||
type: 'options',
|
||||
noDataExpression: true,
|
||||
options: [
|
||||
{
|
||||
name: 'Block',
|
||||
value: 'block',
|
||||
},
|
||||
{
|
||||
name: 'Database',
|
||||
value: 'database',
|
||||
},
|
||||
{
|
||||
name: 'Database Page',
|
||||
value: 'databasePage',
|
||||
},
|
||||
{
|
||||
name: 'Page',
|
||||
value: 'page',
|
||||
},
|
||||
{
|
||||
name: 'User',
|
||||
value: 'user',
|
||||
},
|
||||
],
|
||||
default: 'page',
|
||||
},
|
||||
...blockOperations,
|
||||
...blockFields,
|
||||
...databaseOperations,
|
||||
...databaseFields,
|
||||
...databasePageOperations,
|
||||
...databasePageFields,
|
||||
...pageOperations,
|
||||
...pageFields,
|
||||
...userOperations,
|
||||
...userFields,
|
||||
],
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * as loadOptions from './loadOptions';
|
||||
@@ -0,0 +1,201 @@
|
||||
import moment from 'moment-timezone';
|
||||
import type { IDataObject, ILoadOptionsFunctions, INodePropertyOptions } from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
extractPageId,
|
||||
getBlockTypesOptions,
|
||||
notionApiRequest,
|
||||
notionApiRequestAllItems,
|
||||
} from '../../shared/GenericFunctions';
|
||||
|
||||
export async function getDatabaseProperties(
|
||||
this: ILoadOptionsFunctions,
|
||||
): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const databaseId = this.getCurrentNodeParameter('databaseId', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const { properties } = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
for (const key of Object.keys(properties as IDataObject)) {
|
||||
//remove parameters that cannot be set from the API.
|
||||
if (
|
||||
![
|
||||
'created_time',
|
||||
'last_edited_time',
|
||||
'created_by',
|
||||
'last_edited_by',
|
||||
'formula',
|
||||
'rollup',
|
||||
].includes(properties[key].type as string)
|
||||
) {
|
||||
returnData.push({
|
||||
name: `${key}`,
|
||||
value: `${key}|${properties[key].type}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
returnData.sort((a, b) => {
|
||||
if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return returnData;
|
||||
}
|
||||
|
||||
export async function getFilterProperties(
|
||||
this: ILoadOptionsFunctions,
|
||||
): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const databaseId = this.getCurrentNodeParameter('databaseId', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const { properties } = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
for (const key of Object.keys(properties as IDataObject)) {
|
||||
returnData.push({
|
||||
name: `${key}`,
|
||||
value: `${key}|${properties[key].type}`,
|
||||
});
|
||||
}
|
||||
returnData.sort((a, b) => {
|
||||
if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return returnData;
|
||||
}
|
||||
|
||||
export async function getBlockTypes(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
return getBlockTypesOptions();
|
||||
}
|
||||
|
||||
export async function getPropertySelectValues(
|
||||
this: ILoadOptionsFunctions,
|
||||
): Promise<INodePropertyOptions[]> {
|
||||
const [name, type] = (this.getCurrentNodeParameter('&key') as string).split('|');
|
||||
const databaseId = this.getCurrentNodeParameter('databaseId', {
|
||||
extractValue: true,
|
||||
}) as string;
|
||||
const resource = this.getCurrentNodeParameter('resource') as string;
|
||||
const operation = this.getCurrentNodeParameter('operation') as string;
|
||||
const { properties } = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
if (resource === 'databasePage') {
|
||||
if (['multi_select', 'select', 'status'].includes(type) && operation === 'getAll') {
|
||||
return properties[name][type].options.map((option: IDataObject) => ({
|
||||
name: option.name,
|
||||
value: option.name,
|
||||
}));
|
||||
} else if (
|
||||
['multi_select', 'select', 'status'].includes(type) &&
|
||||
['create', 'update'].includes(operation)
|
||||
) {
|
||||
return properties[name][type].options.map((option: IDataObject) => ({
|
||||
name: option.name,
|
||||
value: option.name,
|
||||
}));
|
||||
}
|
||||
}
|
||||
return properties[name][type].options.map((option: IDataObject) => ({
|
||||
name: option.name,
|
||||
value: option.id,
|
||||
}));
|
||||
}
|
||||
|
||||
export async function getUsers(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const users = await notionApiRequestAllItems.call(this, 'results', 'GET', '/users');
|
||||
for (const user of users) {
|
||||
if (user.type === 'person') {
|
||||
returnData.push({
|
||||
name: user.name,
|
||||
value: user.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
return returnData;
|
||||
}
|
||||
|
||||
export async function getDatabaseIdFromPage(
|
||||
this: ILoadOptionsFunctions,
|
||||
): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
const pageId = extractPageId(
|
||||
this.getCurrentNodeParameter('pageId', { extractValue: true }) as string,
|
||||
);
|
||||
const {
|
||||
parent: { database_id: databaseId },
|
||||
} = await notionApiRequest.call(this, 'GET', `/pages/${pageId}`);
|
||||
const { properties } = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
for (const key of Object.keys(properties as IDataObject)) {
|
||||
//remove parameters that cannot be set from the API.
|
||||
if (
|
||||
![
|
||||
'created_time',
|
||||
'last_edited_time',
|
||||
'created_by',
|
||||
'last_edited_by',
|
||||
'formula',
|
||||
'rollup',
|
||||
].includes(properties[key].type as string)
|
||||
) {
|
||||
returnData.push({
|
||||
name: `${key}`,
|
||||
value: `${key}|${properties[key].type}`,
|
||||
});
|
||||
}
|
||||
}
|
||||
returnData.sort((a, b) => {
|
||||
if (a.name.toLocaleLowerCase() < b.name.toLocaleLowerCase()) {
|
||||
return -1;
|
||||
}
|
||||
if (a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase()) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
return returnData;
|
||||
}
|
||||
|
||||
export async function getDatabaseOptionsFromPage(
|
||||
this: ILoadOptionsFunctions,
|
||||
): Promise<INodePropertyOptions[]> {
|
||||
const pageId = extractPageId(
|
||||
this.getCurrentNodeParameter('pageId', { extractValue: true }) as string,
|
||||
);
|
||||
const [name, type] = (this.getCurrentNodeParameter('&key') as string).split('|');
|
||||
const {
|
||||
parent: { database_id: databaseId },
|
||||
} = await notionApiRequest.call(this, 'GET', `/pages/${pageId}`);
|
||||
const { properties } = await notionApiRequest.call(this, 'GET', `/databases/${databaseId}`);
|
||||
return properties[name][type].options.map((option: IDataObject) => ({
|
||||
name: option.name,
|
||||
value: option.name,
|
||||
}));
|
||||
}
|
||||
|
||||
// Get all the timezones to display them to user so that they can
|
||||
// select them easily
|
||||
export async function getTimezones(this: ILoadOptionsFunctions): Promise<INodePropertyOptions[]> {
|
||||
const returnData: INodePropertyOptions[] = [];
|
||||
for (const timezone of moment.tz.names()) {
|
||||
const timezoneName = timezone;
|
||||
const timezoneId = timezone;
|
||||
returnData.push({
|
||||
name: timezoneName,
|
||||
value: timezoneId,
|
||||
});
|
||||
}
|
||||
returnData.unshift({
|
||||
name: 'Default',
|
||||
value: 'default',
|
||||
description: 'Timezone set in n8n',
|
||||
});
|
||||
return returnData;
|
||||
}
|
||||
Reference in New Issue
Block a user