Skip to content

Commit 4cd679b

Browse files
authored
Merge pull request #21 from asnunes/redirect-page-handle
feat: handle redirect chunk fetch error
2 parents e48aaa2 + e190430 commit 4cd679b

File tree

9 files changed

+89
-11
lines changed

9 files changed

+89
-11
lines changed

.eslintrc.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ module.exports = {
55
sourceType: 'module',
66
},
77
extends: [
8-
'plugin:@typescript-eslint/recommended',
9-
'prettier/@typescript-eslint',
108
'plugin:prettier/recommended', // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
119
],
1210
rules: {},
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { PageChunkValidator } from '../../../../../src/infra/usecases/to-notion-api-content-responses/validation/page-chunk';
2+
3+
describe('PageChunkValidator', () => {
4+
it('should not return an error if status is 200', () => {
5+
const sut = new PageChunkValidator('any_id', 200);
6+
7+
const error = sut.validate();
8+
9+
expect(error).toBeNull();
10+
});
11+
12+
it('should return NotionPageAccessError error if status is 401', () => {
13+
const sut = new PageChunkValidator('any_id', 401);
14+
15+
const error = sut.validate();
16+
17+
expect(error?.name).toBe('NotionPageAccessError');
18+
});
19+
20+
it('should return NotionPageAccessError error if status is 403', () => {
21+
const sut = new PageChunkValidator('any_id', 403);
22+
23+
const error = sut.validate();
24+
25+
expect(error?.name).toBe('NotionPageAccessError');
26+
});
27+
28+
it('should return NotionPageNotFound error if status is 404', () => {
29+
const sut = new PageChunkValidator('any_id', 404);
30+
31+
const error = sut.validate();
32+
33+
expect(error?.name).toBe('NotionPageNotFound');
34+
});
35+
36+
it('should return NotionPageNotFound error if status is 400', () => {
37+
const sut = new PageChunkValidator('any_id', 400);
38+
39+
const error = sut.validate();
40+
41+
expect(error?.name).toBe('NotionPageNotFound');
42+
});
43+
});

package-lock.json

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "notion-page-to-html",
3-
"version": "1.1.2",
3+
"version": "1.1.3",
44
"description": "It converts public notion pages to html from url",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

src/data/usecases/blocks-to-html-converter/block-parsers/youtube-video.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ export class YouTubeVideoBlockToHtml implements ToHtml {
2222
}
2323

2424
private get _youtubeId(): string | void {
25-
const youtubeIdMatcher = /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/gi;
25+
const youtubeIdMatcher =
26+
/(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/\s]{11})/gi;
2627
return youtubeIdMatcher.exec(this._src)?.[1];
2728
}
2829

src/infra/errors/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './missing-content';
22
export * from './missing-page-id';
33
export * from './notion-page-access';
44
export * from './invalid-page-url';
5+
export * from './notion-page-not-found';
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export class NotionPageNotFound extends Error {
2+
constructor(pageId: string) {
3+
super(
4+
`Can not find Notion Page of id ${pageId}. Is the url correct? It is the original page or a redirect page (not supported)?`,
5+
);
6+
this.name = 'NotionPageNotFound';
7+
}
8+
}

src/infra/usecases/to-notion-api-content-responses/notion-api-page-fetcher.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { HttpPostClient, HttpResponse } from '../../../data/protocols/http-request';
22
import { NotionApiContentResponse } from '../../protocols/notion-api-content-response';
33
import { NotionPageIdValidator, PageRecordValidator } from './validation';
4+
import { PageChunkValidator } from './validation/page-chunk';
45

56
const NOTION_API_PATH = 'https://www.notion.so/api/v3/';
67

@@ -18,11 +19,12 @@ export class NotionApiPageFetcher {
1819

1920
async getNotionPageContents(): Promise<NotionApiContentResponse[]> {
2021
const pageRecords = await this._fetchRecordValues();
21-
2222
const pageRecordError = new PageRecordValidator(this._notionPageId, pageRecords).validate();
2323
if (pageRecordError) throw pageRecordError;
2424

2525
const chunk = await this._fetchPageChunk();
26+
const chunkError = new PageChunkValidator(this._notionPageId, chunk.status).validate();
27+
if (chunkError) throw chunkError;
2628

2729
const pageData = pageRecords.data as Record<string, any>;
2830
const chunkData = chunk.data as Record<string, any>;
@@ -107,7 +109,7 @@ export class NotionApiPageFetcher {
107109
});
108110
}
109111

110-
private async _fetchPageChunk(): Promise<HttpResponse> {
112+
private _fetchPageChunk(): Promise<HttpResponse> {
111113
return this._httpPostClient.post(NOTION_API_PATH + 'loadPageChunk', {
112114
pageId: this._notionPageId,
113115
limit: 999999,
@@ -119,12 +121,12 @@ export class NotionApiPageFetcher {
119121
});
120122
}
121123

122-
private async _fetchRecordValuesByContentIds(contentIds: string[]): Promise<HttpResponse> {
124+
private _fetchRecordValuesByContentIds(contentIds: string[]): Promise<HttpResponse> {
123125
if (contentIds.length === 0)
124-
return {
126+
return Promise.resolve({
125127
status: 200,
126128
data: {},
127-
};
129+
});
128130

129131
return this._httpPostClient.post(NOTION_API_PATH + 'syncRecordValues', {
130132
requests: contentIds.map((id) => ({
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { NotionPageAccessError, NotionPageNotFound } from '../../../../infra/errors';
2+
import { Validation } from '../../../protocols/validation';
3+
4+
export class PageChunkValidator implements Validation {
5+
private readonly _notionPageId: string;
6+
private readonly _pageChunkStatus: number;
7+
8+
constructor(notionPageId: string, pageChunkStatus: number) {
9+
this._notionPageId = notionPageId;
10+
this._pageChunkStatus = pageChunkStatus;
11+
}
12+
13+
validate(): Error | null {
14+
if ([401, 403].includes(this._pageChunkStatus)) {
15+
return new NotionPageAccessError(this._notionPageId);
16+
}
17+
18+
if ([400, 404].includes(this._pageChunkStatus)) {
19+
return new NotionPageNotFound(this._notionPageId);
20+
}
21+
22+
return null;
23+
}
24+
}

0 commit comments

Comments
 (0)