From 7848c19f543d5f5f62b89cc5644639c6afdb8fa6 Mon Sep 17 00:00:00 2001 From: Jon Date: Wed, 24 Jul 2024 11:27:07 +0100 Subject: [PATCH] fix(Notion Node): Fix issue preventing some database page urls from working (#10070) --- .../descriptions/DatabasePageDescription.ts | 28 ++++----- .../shared/descriptions/PageDescription.ts | 12 ++-- .../Notion/test/GenericFunctions.test.ts | 61 ++++++++++++++++++- 3 files changed, 80 insertions(+), 21 deletions(-) diff --git a/packages/nodes-base/nodes/Notion/shared/descriptions/DatabasePageDescription.ts b/packages/nodes-base/nodes/Notion/shared/descriptions/DatabasePageDescription.ts index 4916a36223..0c2e71b0c2 100644 --- a/packages/nodes-base/nodes/Notion/shared/descriptions/DatabasePageDescription.ts +++ b/packages/nodes-base/nodes/Notion/shared/descriptions/DatabasePageDescription.ts @@ -601,7 +601,7 @@ export const databasePageFields: INodeProperties[] = [ type: 'regex', properties: { regex: - '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{2,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12}).*', + '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{1,}-)?([0-9a-f]{8}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{12}).*', errorMessage: 'Not a valid Notion Database Page URL', }, }, @@ -609,7 +609,7 @@ export const databasePageFields: INodeProperties[] = [ extractValue: { type: 'regex', regex: - '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{2,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12})', + '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{1,}-)?([0-9a-f]{8}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{12})', }, }, { @@ -622,14 +622,14 @@ export const databasePageFields: INodeProperties[] = [ type: 'regex', properties: { regex: - '^(([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12})|([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}))[ \t]*', + '^(([0-9a-f]{8}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{12})|([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}))[ \t]*', errorMessage: 'Not a valid Notion Database Page ID', }, }, ], extractValue: { type: 'regex', - regex: '^([0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12})', + regex: '^([0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12})', }, url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}', }, @@ -1070,7 +1070,7 @@ export const databasePageFields: INodeProperties[] = [ type: 'regex', properties: { regex: - '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{2,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12}).*', + '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{1,}-)?([0-9a-f]{8}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{12}).*', errorMessage: 'Not a valid Notion Database Page URL', }, }, @@ -1078,7 +1078,7 @@ export const databasePageFields: INodeProperties[] = [ extractValue: { type: 'regex', regex: - '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{2,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12})', + '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{1,}-)?([0-9a-f]{8}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{12})', }, }, { @@ -1091,14 +1091,14 @@ export const databasePageFields: INodeProperties[] = [ type: 'regex', properties: { regex: - '^(([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12})|([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}))[ \t]*', + '^(([0-9a-f]{8}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{12})|([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}))[ \t]*', errorMessage: 'Not a valid Notion Database Page ID', }, }, ], extractValue: { type: 'regex', - regex: '^([0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12})', + regex: '^([0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12})', }, url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}', }, @@ -1161,15 +1161,15 @@ export const databasePageFields: INodeProperties[] = [ type: 'regex', properties: { regex: - '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12}).*', - errorMessage: 'Not a valid Notion Database URL', + '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{1,}-)?([0-9a-f]{8}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{12}).*', + errorMessage: 'Not a valid Notion Database Page URL', }, }, ], extractValue: { type: 'regex', regex: - '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12})', + '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{1,}-)?([0-9a-f]{8}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{12})', }, }, { @@ -1182,14 +1182,14 @@ export const databasePageFields: INodeProperties[] = [ type: 'regex', properties: { regex: - '^(([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12})|([0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}))[ \t]*', - errorMessage: 'Not a valid Notion Database ID', + '^(([0-9a-f]{8}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{12})|([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}))[ \t]*', + errorMessage: 'Not a valid Notion Database Page ID', }, }, ], extractValue: { type: 'regex', - regex: '^([0-9a-f]{8}-?[0-9a-f]{4}-?4[0-9a-f]{3}-?[89ab][0-9a-f]{3}-?[0-9a-f]{12})', + regex: '^([0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12})', }, url: '=https://www.notion.so/{{$value.replace(/-/g, "")}}', }, diff --git a/packages/nodes-base/nodes/Notion/shared/descriptions/PageDescription.ts b/packages/nodes-base/nodes/Notion/shared/descriptions/PageDescription.ts index d0abb0f3f0..602c28694f 100644 --- a/packages/nodes-base/nodes/Notion/shared/descriptions/PageDescription.ts +++ b/packages/nodes-base/nodes/Notion/shared/descriptions/PageDescription.ts @@ -94,15 +94,15 @@ export const pageFields: INodeProperties[] = [ type: 'regex', properties: { regex: - '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{2,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12}).*', - errorMessage: 'Not a valid Notion Page URL', + '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{1,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12}).*', + errorMessage: 'Not a valid Notion Database Page URL', }, }, ], extractValue: { type: 'regex', regex: - '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{2,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12})', + '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{1,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12})', }, }, { @@ -174,15 +174,15 @@ export const pageFields: INodeProperties[] = [ type: 'regex', properties: { regex: - '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{2,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12}).*', - errorMessage: 'Not a valid Notion Page URL', + '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{1,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12}).*', + errorMessage: 'Not a valid Notion Database Page URL', }, }, ], extractValue: { type: 'regex', regex: - '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{2,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12})', + '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{1,}-)?([0-9a-f]{8}[0-9a-f]{4}4[0-9a-f]{3}[89ab][0-9a-f]{3}[0-9a-f]{12})', }, }, { diff --git a/packages/nodes-base/nodes/Notion/test/GenericFunctions.test.ts b/packages/nodes-base/nodes/Notion/test/GenericFunctions.test.ts index dc5baba799..543292abe8 100644 --- a/packages/nodes-base/nodes/Notion/test/GenericFunctions.test.ts +++ b/packages/nodes-base/nodes/Notion/test/GenericFunctions.test.ts @@ -1,4 +1,4 @@ -import { formatBlocks } from '../shared/GenericFunctions'; +import { extractPageId, formatBlocks } from '../shared/GenericFunctions'; describe('Test NotionV2, formatBlocks', () => { it('should format to_do block', () => { @@ -31,3 +31,62 @@ describe('Test NotionV2, formatBlocks', () => { ]); }); }); + +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', () => { + const extractPattern = + '(?:https|http)://www.notion.so/(?:[a-z0-9-]{2,}/)?(?:[a-zA-Z0-9-]{1,}-)?([0-9a-f]{8}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{4}[0-9a-f]{12})'; + // RLC does some Regex extraction before extractPageId is called + const extractIdFromUrl = (url: string): string => { + const match = url.match(extractPattern); + 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); + } + }); + }); +});