@slogvo/notion-client 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +26 -0
- package/README.md +19 -0
- package/build/index.d.ts +79 -0
- package/build/index.js +548 -0
- package/build/index.js.map +1 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vue Notion X Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
This project extends MIT-licensed work from react-notion-x by Travis Fischer
|
|
26
|
+
and other contributors.
|
package/README.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @slogvo/notion-client
|
|
2
|
+
|
|
3
|
+
> Robust TypeScript client for the unofficial Notion API. Works in Node.js and Browser.
|
|
4
|
+
>
|
|
5
|
+
> Client kết nối Notion API viết bằng TypeScript, hoạt động trên cả server và trình duyệt. 🚀
|
|
6
|
+
>
|
|
7
|
+
> 非公式 Notion API 向けの強力な TypeScript クライアント。 Node.js およびブラウザで動作します。 ⚡️
|
|
8
|
+
|
|
9
|
+
Part of the [vue-notion](https://github.com/slogvo/vue-notion) monorepo.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @slogvo/notion-client
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## License
|
|
18
|
+
|
|
19
|
+
MIT
|
package/build/index.d.ts
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as notion from '@slogvo/notion-types';
|
|
2
|
+
import { FetchOptions } from 'ofetch';
|
|
3
|
+
|
|
4
|
+
interface SignedUrlRequest {
|
|
5
|
+
permissionRecord: PermissionRecord;
|
|
6
|
+
url: string;
|
|
7
|
+
}
|
|
8
|
+
interface PermissionRecord {
|
|
9
|
+
table: string;
|
|
10
|
+
id: notion.ID;
|
|
11
|
+
}
|
|
12
|
+
interface SignedUrlResponse {
|
|
13
|
+
signedUrls: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Main Notion API client.
|
|
18
|
+
*/
|
|
19
|
+
declare class NotionAPI {
|
|
20
|
+
private readonly _apiBaseUrl;
|
|
21
|
+
private readonly _authToken?;
|
|
22
|
+
private readonly _activeUser?;
|
|
23
|
+
private readonly _userTimeZone;
|
|
24
|
+
private readonly _ofetchOptions?;
|
|
25
|
+
constructor({ apiBaseUrl, authToken, activeUser, userTimeZone, ofetchOptions }?: {
|
|
26
|
+
apiBaseUrl?: string;
|
|
27
|
+
authToken?: string;
|
|
28
|
+
userLocale?: string;
|
|
29
|
+
userTimeZone?: string;
|
|
30
|
+
activeUser?: string;
|
|
31
|
+
ofetchOptions?: FetchOptions;
|
|
32
|
+
});
|
|
33
|
+
getPage(pageId: string, { concurrency, fetchMissingBlocks, fetchCollections, signFileUrls, chunkLimit, chunkNumber, throwOnCollectionErrors, collectionReducerLimit, fetchRelationPages, ofetchOptions }?: {
|
|
34
|
+
concurrency?: number;
|
|
35
|
+
fetchMissingBlocks?: boolean;
|
|
36
|
+
fetchCollections?: boolean;
|
|
37
|
+
signFileUrls?: boolean;
|
|
38
|
+
chunkLimit?: number;
|
|
39
|
+
chunkNumber?: number;
|
|
40
|
+
throwOnCollectionErrors?: boolean;
|
|
41
|
+
collectionReducerLimit?: number;
|
|
42
|
+
fetchRelationPages?: boolean;
|
|
43
|
+
ofetchOptions?: FetchOptions;
|
|
44
|
+
}): Promise<notion.ExtendedRecordMap>;
|
|
45
|
+
fetchRelationPages: (recordMap: notion.ExtendedRecordMap, ofetchOptions: FetchOptions | undefined) => Promise<notion.BlockMap>;
|
|
46
|
+
extractRelationPageIdsFromBlock: (blockValue: any, collectionSchema: any) => Set<string>;
|
|
47
|
+
addSignedUrls({ recordMap, contentBlockIds, ofetchOptions }: {
|
|
48
|
+
recordMap: notion.ExtendedRecordMap;
|
|
49
|
+
contentBlockIds?: string[];
|
|
50
|
+
ofetchOptions?: FetchOptions;
|
|
51
|
+
}): Promise<void>;
|
|
52
|
+
getPageRaw(pageId: string, { ofetchOptions, chunkLimit, chunkNumber }?: {
|
|
53
|
+
chunkLimit?: number;
|
|
54
|
+
chunkNumber?: number;
|
|
55
|
+
ofetchOptions?: FetchOptions;
|
|
56
|
+
}): Promise<notion.PageChunk>;
|
|
57
|
+
getCollectionData(collectionId: string, collectionViewId: string, collectionView?: any, { limit, searchQuery, userTimeZone, loadContentCover, spaceId, ofetchOptions }?: {
|
|
58
|
+
type?: notion.CollectionViewType;
|
|
59
|
+
limit?: number;
|
|
60
|
+
searchQuery?: string;
|
|
61
|
+
userTimeZone?: string;
|
|
62
|
+
userLocale?: string;
|
|
63
|
+
loadContentCover?: boolean;
|
|
64
|
+
spaceId?: string;
|
|
65
|
+
ofetchOptions?: FetchOptions;
|
|
66
|
+
}): Promise<notion.CollectionInstance>;
|
|
67
|
+
getUsers(userIds: string[], ofetchOptions?: FetchOptions): Promise<notion.RecordValues<notion.User>>;
|
|
68
|
+
getBlocks(blockIds: string[], ofetchOptions?: FetchOptions): Promise<notion.PageChunk>;
|
|
69
|
+
getSignedFileUrls(urls: SignedUrlRequest[], ofetchOptions?: FetchOptions): Promise<SignedUrlResponse>;
|
|
70
|
+
search(params: notion.SearchParams, ofetchOptions?: FetchOptions): Promise<notion.SearchResults>;
|
|
71
|
+
fetch<T>({ endpoint, body, ofetchOptions, headers: clientHeaders }: {
|
|
72
|
+
endpoint: string;
|
|
73
|
+
body: object;
|
|
74
|
+
ofetchOptions?: FetchOptions;
|
|
75
|
+
headers?: any;
|
|
76
|
+
}): Promise<T>;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export { NotionAPI, type PermissionRecord, type SignedUrlRequest, type SignedUrlResponse };
|
package/build/index.js
ADDED
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
5
|
+
// src/notion-api.ts
|
|
6
|
+
import {
|
|
7
|
+
getBlockCollectionId,
|
|
8
|
+
getPageContentBlockIds,
|
|
9
|
+
parsePageId,
|
|
10
|
+
uuidToId
|
|
11
|
+
} from "@slogvo/notion-utils";
|
|
12
|
+
import { ofetch } from "ofetch";
|
|
13
|
+
import pMap from "p-map";
|
|
14
|
+
var NotionAPI = class {
|
|
15
|
+
constructor({
|
|
16
|
+
apiBaseUrl = "https://www.notion.so/api/v3",
|
|
17
|
+
authToken,
|
|
18
|
+
activeUser,
|
|
19
|
+
userTimeZone = "America/New_York",
|
|
20
|
+
ofetchOptions
|
|
21
|
+
} = {}) {
|
|
22
|
+
__publicField(this, "_apiBaseUrl");
|
|
23
|
+
__publicField(this, "_authToken");
|
|
24
|
+
__publicField(this, "_activeUser");
|
|
25
|
+
__publicField(this, "_userTimeZone");
|
|
26
|
+
__publicField(this, "_ofetchOptions");
|
|
27
|
+
__publicField(this, "fetchRelationPages", async (recordMap, ofetchOptions) => {
|
|
28
|
+
var _a, _b;
|
|
29
|
+
const maxIterations = 10;
|
|
30
|
+
for (let i = 0; i < maxIterations; ++i) {
|
|
31
|
+
const relationPageIdsThisIteration = /* @__PURE__ */ new Set();
|
|
32
|
+
for (const blockId of Object.keys(recordMap.block)) {
|
|
33
|
+
const blockValue = (_a = recordMap.block[blockId]) == null ? void 0 : _a.value;
|
|
34
|
+
if ((blockValue == null ? void 0 : blockValue.parent_table) === "collection" && (blockValue == null ? void 0 : blockValue.parent_id)) {
|
|
35
|
+
const collection = (_b = recordMap.collection[blockValue.parent_id]) == null ? void 0 : _b.value;
|
|
36
|
+
if (collection == null ? void 0 : collection.schema) {
|
|
37
|
+
const ids = this.extractRelationPageIdsFromBlock(
|
|
38
|
+
blockValue,
|
|
39
|
+
collection.schema
|
|
40
|
+
);
|
|
41
|
+
for (const id of ids) relationPageIdsThisIteration.add(id);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const missingRelationPageIds = Array.from(
|
|
46
|
+
relationPageIdsThisIteration
|
|
47
|
+
).filter((id) => {
|
|
48
|
+
var _a2;
|
|
49
|
+
return !((_a2 = recordMap.block[id]) == null ? void 0 : _a2.value);
|
|
50
|
+
});
|
|
51
|
+
if (!missingRelationPageIds.length) break;
|
|
52
|
+
try {
|
|
53
|
+
const newBlocks = await this.getBlocks(
|
|
54
|
+
missingRelationPageIds,
|
|
55
|
+
ofetchOptions
|
|
56
|
+
).then((res) => res.recordMap.block);
|
|
57
|
+
recordMap.block = { ...recordMap.block, ...newBlocks };
|
|
58
|
+
} catch (err) {
|
|
59
|
+
console.warn(
|
|
60
|
+
"NotionAPI getBlocks error during fetchRelationPages:",
|
|
61
|
+
err
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return recordMap.block;
|
|
66
|
+
});
|
|
67
|
+
__publicField(this, "extractRelationPageIdsFromBlock", (blockValue, collectionSchema) => {
|
|
68
|
+
var _a;
|
|
69
|
+
const pageIds = /* @__PURE__ */ new Set();
|
|
70
|
+
for (const propertyId of Object.keys(blockValue.properties || {})) {
|
|
71
|
+
const schema = collectionSchema[propertyId];
|
|
72
|
+
if ((schema == null ? void 0 : schema.type) === "relation") {
|
|
73
|
+
const decorations = blockValue.properties[propertyId];
|
|
74
|
+
if (Array.isArray(decorations)) {
|
|
75
|
+
for (const decoration of decorations) {
|
|
76
|
+
if (Array.isArray(decoration) && decoration.length > 1 && decoration[0] === "\u2023") {
|
|
77
|
+
const pagePointer = (_a = decoration[1]) == null ? void 0 : _a[0];
|
|
78
|
+
if (Array.isArray(pagePointer) && pagePointer.length > 1 && pagePointer[0] === "p") {
|
|
79
|
+
pageIds.add(pagePointer[1]);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return pageIds;
|
|
87
|
+
});
|
|
88
|
+
this._apiBaseUrl = apiBaseUrl;
|
|
89
|
+
this._authToken = authToken;
|
|
90
|
+
this._activeUser = activeUser;
|
|
91
|
+
this._userTimeZone = userTimeZone;
|
|
92
|
+
this._ofetchOptions = ofetchOptions;
|
|
93
|
+
}
|
|
94
|
+
async getPage(pageId, {
|
|
95
|
+
concurrency = 3,
|
|
96
|
+
fetchMissingBlocks = true,
|
|
97
|
+
fetchCollections = true,
|
|
98
|
+
signFileUrls = true,
|
|
99
|
+
chunkLimit = 100,
|
|
100
|
+
chunkNumber = 0,
|
|
101
|
+
throwOnCollectionErrors = false,
|
|
102
|
+
collectionReducerLimit = 999,
|
|
103
|
+
fetchRelationPages = false,
|
|
104
|
+
ofetchOptions
|
|
105
|
+
} = {}) {
|
|
106
|
+
var _a, _b, _c;
|
|
107
|
+
const page = await this.getPageRaw(pageId, {
|
|
108
|
+
chunkLimit,
|
|
109
|
+
chunkNumber,
|
|
110
|
+
ofetchOptions
|
|
111
|
+
});
|
|
112
|
+
const recordMap = page == null ? void 0 : page.recordMap;
|
|
113
|
+
if (!(recordMap == null ? void 0 : recordMap.block)) {
|
|
114
|
+
throw new Error(`Notion page not found "${uuidToId(pageId)}"`);
|
|
115
|
+
}
|
|
116
|
+
recordMap.collection = (_a = recordMap.collection) != null ? _a : {};
|
|
117
|
+
recordMap.collection_view = (_b = recordMap.collection_view) != null ? _b : {};
|
|
118
|
+
recordMap.notion_user = (_c = recordMap.notion_user) != null ? _c : {};
|
|
119
|
+
recordMap.collection_query = {};
|
|
120
|
+
recordMap.signed_urls = {};
|
|
121
|
+
if (fetchMissingBlocks) {
|
|
122
|
+
while (true) {
|
|
123
|
+
const pendingBlockIds = getPageContentBlockIds(recordMap).filter(
|
|
124
|
+
(id) => !recordMap.block[id]
|
|
125
|
+
);
|
|
126
|
+
if (!pendingBlockIds.length) {
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
const newBlocks = await this.getBlocks(
|
|
130
|
+
pendingBlockIds,
|
|
131
|
+
ofetchOptions
|
|
132
|
+
).then((res) => res.recordMap.block);
|
|
133
|
+
recordMap.block = { ...recordMap.block, ...newBlocks };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
const contentBlockIds = getPageContentBlockIds(recordMap);
|
|
137
|
+
if (fetchCollections) {
|
|
138
|
+
const allCollectionInstances = contentBlockIds.flatMap((blockId) => {
|
|
139
|
+
var _a2, _b2;
|
|
140
|
+
const block = (_a2 = recordMap.block[blockId]) == null ? void 0 : _a2.value;
|
|
141
|
+
const collectionId = block && (block.type === "collection_view" || block.type === "collection_view_page") && getBlockCollectionId(block, recordMap);
|
|
142
|
+
if (collectionId) {
|
|
143
|
+
const spaceId = block == null ? void 0 : block.space_id;
|
|
144
|
+
return (_b2 = block.view_ids) == null ? void 0 : _b2.map((collectionViewId) => ({
|
|
145
|
+
collectionId,
|
|
146
|
+
collectionViewId,
|
|
147
|
+
spaceId
|
|
148
|
+
}));
|
|
149
|
+
} else {
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
await pMap(
|
|
154
|
+
allCollectionInstances,
|
|
155
|
+
async (collectionInstance) => {
|
|
156
|
+
var _a2, _b2;
|
|
157
|
+
const { collectionId, collectionViewId, spaceId } = collectionInstance;
|
|
158
|
+
const collectionView = (_a2 = recordMap.collection_view[collectionViewId]) == null ? void 0 : _a2.value;
|
|
159
|
+
try {
|
|
160
|
+
const collectionData = await this.getCollectionData(
|
|
161
|
+
collectionId,
|
|
162
|
+
collectionViewId,
|
|
163
|
+
collectionView,
|
|
164
|
+
{
|
|
165
|
+
limit: collectionReducerLimit,
|
|
166
|
+
spaceId,
|
|
167
|
+
ofetchOptions
|
|
168
|
+
}
|
|
169
|
+
);
|
|
170
|
+
recordMap.block = {
|
|
171
|
+
...recordMap.block,
|
|
172
|
+
...collectionData.recordMap.block
|
|
173
|
+
};
|
|
174
|
+
recordMap.collection = {
|
|
175
|
+
...recordMap.collection,
|
|
176
|
+
...collectionData.recordMap.collection
|
|
177
|
+
};
|
|
178
|
+
recordMap.collection_view = {
|
|
179
|
+
...recordMap.collection_view,
|
|
180
|
+
...collectionData.recordMap.collection_view
|
|
181
|
+
};
|
|
182
|
+
recordMap.notion_user = {
|
|
183
|
+
...recordMap.notion_user,
|
|
184
|
+
...collectionData.recordMap.notion_user
|
|
185
|
+
};
|
|
186
|
+
recordMap.collection_query[collectionId] = {
|
|
187
|
+
...recordMap.collection_query[collectionId],
|
|
188
|
+
[collectionViewId]: (_b2 = collectionData.result) == null ? void 0 : _b2.reducerResults
|
|
189
|
+
};
|
|
190
|
+
} catch (err) {
|
|
191
|
+
console.warn(
|
|
192
|
+
"NotionAPI collectionQuery error",
|
|
193
|
+
{ pageId, collectionId, collectionViewId },
|
|
194
|
+
err.message
|
|
195
|
+
);
|
|
196
|
+
if (throwOnCollectionErrors) {
|
|
197
|
+
throw err;
|
|
198
|
+
} else {
|
|
199
|
+
console.error(err);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
concurrency
|
|
205
|
+
}
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
if (signFileUrls) {
|
|
209
|
+
await this.addSignedUrls({ recordMap, contentBlockIds, ofetchOptions });
|
|
210
|
+
}
|
|
211
|
+
if (fetchRelationPages) {
|
|
212
|
+
const newBlocks = await this.fetchRelationPages(recordMap, ofetchOptions);
|
|
213
|
+
recordMap.block = { ...recordMap.block, ...newBlocks };
|
|
214
|
+
}
|
|
215
|
+
return recordMap;
|
|
216
|
+
}
|
|
217
|
+
async addSignedUrls({
|
|
218
|
+
recordMap,
|
|
219
|
+
contentBlockIds,
|
|
220
|
+
ofetchOptions = {}
|
|
221
|
+
}) {
|
|
222
|
+
recordMap.signed_urls = {};
|
|
223
|
+
if (!contentBlockIds) {
|
|
224
|
+
contentBlockIds = getPageContentBlockIds(recordMap);
|
|
225
|
+
}
|
|
226
|
+
const allFileInstances = contentBlockIds.flatMap((blockId) => {
|
|
227
|
+
var _a, _b, _c, _d, _e, _f;
|
|
228
|
+
const block = (_a = recordMap.block[blockId]) == null ? void 0 : _a.value;
|
|
229
|
+
if (block && (block.type === "pdf" || block.type === "audio" || block.type === "image" && ((_b = block.file_ids) == null ? void 0 : _b.length) || block.type === "video" || block.type === "file" || block.type === "page")) {
|
|
230
|
+
const source = block.type === "page" ? (_c = block.format) == null ? void 0 : _c.page_cover : (_f = (_e = (_d = block.properties) == null ? void 0 : _d.source) == null ? void 0 : _e[0]) == null ? void 0 : _f[0];
|
|
231
|
+
if (source) {
|
|
232
|
+
if (source.includes("secure.notion-static.com") || source.includes("prod-files-secure") || source.includes("attachment:")) {
|
|
233
|
+
return {
|
|
234
|
+
permissionRecord: {
|
|
235
|
+
table: "block",
|
|
236
|
+
id: block.id
|
|
237
|
+
},
|
|
238
|
+
url: source
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
return [];
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return [];
|
|
245
|
+
});
|
|
246
|
+
if (allFileInstances.length > 0) {
|
|
247
|
+
try {
|
|
248
|
+
const { signedUrls } = await this.getSignedFileUrls(
|
|
249
|
+
allFileInstances,
|
|
250
|
+
ofetchOptions
|
|
251
|
+
);
|
|
252
|
+
if (signedUrls.length === allFileInstances.length) {
|
|
253
|
+
for (const [i, file] of allFileInstances.entries()) {
|
|
254
|
+
const signedUrl = signedUrls[i];
|
|
255
|
+
if (!signedUrl) continue;
|
|
256
|
+
const blockId = file.permissionRecord.id;
|
|
257
|
+
if (!blockId) continue;
|
|
258
|
+
recordMap.signed_urls[blockId] = signedUrl;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
} catch (err) {
|
|
262
|
+
console.warn("NotionAPI getSignedfileUrls error", err);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
async getPageRaw(pageId, {
|
|
267
|
+
ofetchOptions,
|
|
268
|
+
chunkLimit = 100,
|
|
269
|
+
chunkNumber = 0
|
|
270
|
+
} = {}) {
|
|
271
|
+
const parsedPageId = parsePageId(pageId);
|
|
272
|
+
if (!parsedPageId) {
|
|
273
|
+
throw new Error(`invalid notion pageId "${pageId}"`);
|
|
274
|
+
}
|
|
275
|
+
const body = {
|
|
276
|
+
pageId: parsedPageId,
|
|
277
|
+
limit: chunkLimit,
|
|
278
|
+
chunkNumber,
|
|
279
|
+
cursor: { stack: [] },
|
|
280
|
+
verticalColumns: false
|
|
281
|
+
};
|
|
282
|
+
return this.fetch({
|
|
283
|
+
endpoint: "loadPageChunk",
|
|
284
|
+
body,
|
|
285
|
+
ofetchOptions
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
async getCollectionData(collectionId, collectionViewId, collectionView, {
|
|
289
|
+
limit = 999,
|
|
290
|
+
searchQuery = "",
|
|
291
|
+
userTimeZone = this._userTimeZone,
|
|
292
|
+
loadContentCover = true,
|
|
293
|
+
spaceId,
|
|
294
|
+
ofetchOptions
|
|
295
|
+
} = {}) {
|
|
296
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
|
|
297
|
+
const type = collectionView == null ? void 0 : collectionView.type;
|
|
298
|
+
const isBoardType = type === "board";
|
|
299
|
+
const groupBy = isBoardType ? (_a = collectionView == null ? void 0 : collectionView.format) == null ? void 0 : _a.board_columns_by : (_b = collectionView == null ? void 0 : collectionView.format) == null ? void 0 : _b.collection_group_by;
|
|
300
|
+
let filters = [];
|
|
301
|
+
if ((_c = collectionView == null ? void 0 : collectionView.format) == null ? void 0 : _c.property_filters) {
|
|
302
|
+
filters = (_d = collectionView.format) == null ? void 0 : _d.property_filters.map(
|
|
303
|
+
(filterObj) => {
|
|
304
|
+
var _a2, _b2;
|
|
305
|
+
return {
|
|
306
|
+
filter: (_a2 = filterObj == null ? void 0 : filterObj.filter) == null ? void 0 : _a2.filter,
|
|
307
|
+
property: (_b2 = filterObj == null ? void 0 : filterObj.filter) == null ? void 0 : _b2.property
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
if ((_f = (_e = collectionView == null ? void 0 : collectionView.query2) == null ? void 0 : _e.filter) == null ? void 0 : _f.filters) {
|
|
313
|
+
filters.push(...collectionView.query2.filter.filters);
|
|
314
|
+
}
|
|
315
|
+
let loader = {
|
|
316
|
+
type: "reducer",
|
|
317
|
+
reducers: {
|
|
318
|
+
collection_group_results: {
|
|
319
|
+
type: "results",
|
|
320
|
+
limit,
|
|
321
|
+
loadContentCover
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
sort: [],
|
|
325
|
+
...collectionView == null ? void 0 : collectionView.query2,
|
|
326
|
+
filter: {
|
|
327
|
+
filters,
|
|
328
|
+
operator: "and"
|
|
329
|
+
},
|
|
330
|
+
searchQuery,
|
|
331
|
+
userTimeZone
|
|
332
|
+
};
|
|
333
|
+
if (groupBy) {
|
|
334
|
+
const groups = ((_g = collectionView == null ? void 0 : collectionView.format) == null ? void 0 : _g.board_columns) || ((_h = collectionView == null ? void 0 : collectionView.format) == null ? void 0 : _h.collection_groups) || [];
|
|
335
|
+
const iterators = [isBoardType ? "board" : "group_aggregation", "results"];
|
|
336
|
+
const operators = {
|
|
337
|
+
checkbox: "checkbox_is",
|
|
338
|
+
url: "string_starts_with",
|
|
339
|
+
text: "string_starts_with",
|
|
340
|
+
select: "enum_is",
|
|
341
|
+
multi_select: "enum_contains",
|
|
342
|
+
created_time: "date_is_within",
|
|
343
|
+
undefined: "is_empty"
|
|
344
|
+
};
|
|
345
|
+
const reducersQuery = {};
|
|
346
|
+
for (const group of groups) {
|
|
347
|
+
const {
|
|
348
|
+
property,
|
|
349
|
+
value: { value, type: type2 }
|
|
350
|
+
} = group;
|
|
351
|
+
for (const iterator of iterators) {
|
|
352
|
+
const iteratorProps = iterator === "results" ? {
|
|
353
|
+
type: iterator,
|
|
354
|
+
limit
|
|
355
|
+
} : {
|
|
356
|
+
type: "aggregation",
|
|
357
|
+
aggregation: {
|
|
358
|
+
aggregator: "count"
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
const isUncategorizedValue = value === void 0;
|
|
362
|
+
const isDateValue = value == null ? void 0 : value.range;
|
|
363
|
+
const queryLabel = isUncategorizedValue ? "uncategorized" : isDateValue ? ((_i = value.range) == null ? void 0 : _i.start_date) || ((_j = value.range) == null ? void 0 : _j.end_date) : (value == null ? void 0 : value.value) || value;
|
|
364
|
+
const queryValue = !isUncategorizedValue && (isDateValue || (value == null ? void 0 : value.value) || value);
|
|
365
|
+
reducersQuery[`${iterator}:${type2}:${queryLabel}`] = {
|
|
366
|
+
...iteratorProps,
|
|
367
|
+
filter: {
|
|
368
|
+
operator: "and",
|
|
369
|
+
filters: [
|
|
370
|
+
{
|
|
371
|
+
property,
|
|
372
|
+
filter: {
|
|
373
|
+
operator: !isUncategorizedValue ? operators[type2] : "is_empty",
|
|
374
|
+
...!isUncategorizedValue && {
|
|
375
|
+
value: {
|
|
376
|
+
type: "exact",
|
|
377
|
+
value: queryValue
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
]
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
const reducerLabel = isBoardType ? "board_columns" : `${type}_groups`;
|
|
388
|
+
loader = {
|
|
389
|
+
type: "reducer",
|
|
390
|
+
reducers: {
|
|
391
|
+
[reducerLabel]: {
|
|
392
|
+
type: "groups",
|
|
393
|
+
version: "v2",
|
|
394
|
+
groupBy,
|
|
395
|
+
...((_k = collectionView == null ? void 0 : collectionView.query2) == null ? void 0 : _k.filter) && {
|
|
396
|
+
filter: (_l = collectionView == null ? void 0 : collectionView.query2) == null ? void 0 : _l.filter
|
|
397
|
+
},
|
|
398
|
+
groupSortPreference: groups.map((group) => {
|
|
399
|
+
var _a2, _b2;
|
|
400
|
+
return {
|
|
401
|
+
property: group == null ? void 0 : group.property,
|
|
402
|
+
value: {
|
|
403
|
+
type: (_a2 = group == null ? void 0 : group.value) == null ? void 0 : _a2.type,
|
|
404
|
+
value: (_b2 = group == null ? void 0 : group.value) == null ? void 0 : _b2.value
|
|
405
|
+
}
|
|
406
|
+
};
|
|
407
|
+
}),
|
|
408
|
+
limit
|
|
409
|
+
},
|
|
410
|
+
...reducersQuery
|
|
411
|
+
},
|
|
412
|
+
...collectionView == null ? void 0 : collectionView.query2,
|
|
413
|
+
searchQuery,
|
|
414
|
+
userTimeZone,
|
|
415
|
+
//TODO: add filters here
|
|
416
|
+
filter: {
|
|
417
|
+
filters,
|
|
418
|
+
operator: "and"
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
const headers = {};
|
|
423
|
+
if (spaceId) {
|
|
424
|
+
headers["x-notion-space-id"] = spaceId;
|
|
425
|
+
}
|
|
426
|
+
return this.fetch({
|
|
427
|
+
endpoint: "queryCollection",
|
|
428
|
+
body: {
|
|
429
|
+
collection: {
|
|
430
|
+
id: collectionId
|
|
431
|
+
},
|
|
432
|
+
collectionView: {
|
|
433
|
+
id: collectionViewId
|
|
434
|
+
},
|
|
435
|
+
source: {
|
|
436
|
+
type: "collection",
|
|
437
|
+
id: collectionId
|
|
438
|
+
},
|
|
439
|
+
loader
|
|
440
|
+
},
|
|
441
|
+
headers,
|
|
442
|
+
ofetchOptions: {
|
|
443
|
+
timeout: 6e4,
|
|
444
|
+
...ofetchOptions,
|
|
445
|
+
params: {
|
|
446
|
+
// TODO: spread ofetchOptions?.searchParams
|
|
447
|
+
src: "initial_load"
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
async getUsers(userIds, ofetchOptions) {
|
|
453
|
+
return this.fetch({
|
|
454
|
+
endpoint: "getRecordValues",
|
|
455
|
+
body: {
|
|
456
|
+
requests: userIds.map((id) => ({ id, table: "notion_user" }))
|
|
457
|
+
},
|
|
458
|
+
ofetchOptions
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
async getBlocks(blockIds, ofetchOptions) {
|
|
462
|
+
return this.fetch({
|
|
463
|
+
endpoint: "syncRecordValuesMain",
|
|
464
|
+
body: {
|
|
465
|
+
requests: blockIds.map((blockId) => ({
|
|
466
|
+
// TODO: when to use table 'space' vs 'block'?
|
|
467
|
+
table: "block",
|
|
468
|
+
id: blockId,
|
|
469
|
+
version: -1
|
|
470
|
+
}))
|
|
471
|
+
},
|
|
472
|
+
ofetchOptions
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
async getSignedFileUrls(urls, ofetchOptions) {
|
|
476
|
+
return this.fetch({
|
|
477
|
+
endpoint: "getSignedFileUrls",
|
|
478
|
+
body: {
|
|
479
|
+
urls
|
|
480
|
+
},
|
|
481
|
+
ofetchOptions
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
async search(params, ofetchOptions) {
|
|
485
|
+
const body = {
|
|
486
|
+
type: "BlocksInAncestor",
|
|
487
|
+
source: "quick_find_public",
|
|
488
|
+
ancestorId: parsePageId(params.ancestorId),
|
|
489
|
+
sort: {
|
|
490
|
+
field: "relevance"
|
|
491
|
+
},
|
|
492
|
+
limit: params.limit || 20,
|
|
493
|
+
query: params.query,
|
|
494
|
+
filters: {
|
|
495
|
+
isDeletedOnly: false,
|
|
496
|
+
isNavigableOnly: false,
|
|
497
|
+
excludeTemplates: true,
|
|
498
|
+
requireEditPermissions: false,
|
|
499
|
+
includePublicPagesWithoutExplicitAccess: true,
|
|
500
|
+
ancestors: [],
|
|
501
|
+
createdBy: [],
|
|
502
|
+
editedBy: [],
|
|
503
|
+
lastEditedTime: {},
|
|
504
|
+
createdTime: {},
|
|
505
|
+
...params.filters
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
return this.fetch({
|
|
509
|
+
endpoint: "search",
|
|
510
|
+
body,
|
|
511
|
+
ofetchOptions
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
async fetch({
|
|
515
|
+
endpoint,
|
|
516
|
+
body,
|
|
517
|
+
ofetchOptions,
|
|
518
|
+
headers: clientHeaders
|
|
519
|
+
}) {
|
|
520
|
+
var _a;
|
|
521
|
+
const headers = {
|
|
522
|
+
...clientHeaders,
|
|
523
|
+
...(_a = this._ofetchOptions) == null ? void 0 : _a.headers,
|
|
524
|
+
...ofetchOptions == null ? void 0 : ofetchOptions.headers,
|
|
525
|
+
"Content-Type": "application/json"
|
|
526
|
+
};
|
|
527
|
+
if (this._authToken) {
|
|
528
|
+
headers.cookie = `token_v2=${this._authToken}`;
|
|
529
|
+
}
|
|
530
|
+
if (this._activeUser) {
|
|
531
|
+
headers["x-notion-active-user-header"] = this._activeUser;
|
|
532
|
+
}
|
|
533
|
+
const url = `${this._apiBaseUrl}/${endpoint}`;
|
|
534
|
+
const res = ofetch(url, {
|
|
535
|
+
method: "POST",
|
|
536
|
+
mode: "no-cors",
|
|
537
|
+
...this._ofetchOptions,
|
|
538
|
+
...ofetchOptions,
|
|
539
|
+
body,
|
|
540
|
+
headers
|
|
541
|
+
});
|
|
542
|
+
return res;
|
|
543
|
+
}
|
|
544
|
+
};
|
|
545
|
+
export {
|
|
546
|
+
NotionAPI
|
|
547
|
+
};
|
|
548
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/notion-api.ts"],"sourcesContent":["// import { promises as fs } from 'fs'\n//import ky, { type Options as OfetchOptions } from 'ky'\n\nimport type * as notion from '@slogvo/notion-types'\nimport {\n getBlockCollectionId,\n getPageContentBlockIds,\n parsePageId,\n uuidToId\n} from '@slogvo/notion-utils'\nimport { type FetchOptions as OfetchOptions, ofetch } from 'ofetch'\nimport pMap from 'p-map'\n\nimport type * as types from './types'\n\n/**\n * Main Notion API client.\n */\nexport class NotionAPI {\n private readonly _apiBaseUrl: string\n private readonly _authToken?: string\n private readonly _activeUser?: string\n private readonly _userTimeZone: string\n private readonly _ofetchOptions?: OfetchOptions\n\n constructor({\n apiBaseUrl = 'https://www.notion.so/api/v3',\n authToken,\n activeUser,\n userTimeZone = 'America/New_York',\n ofetchOptions\n }: {\n apiBaseUrl?: string\n authToken?: string\n userLocale?: string\n userTimeZone?: string\n activeUser?: string\n ofetchOptions?: OfetchOptions\n } = {}) {\n this._apiBaseUrl = apiBaseUrl\n this._authToken = authToken\n this._activeUser = activeUser\n this._userTimeZone = userTimeZone\n this._ofetchOptions = ofetchOptions\n }\n\n public async getPage(\n pageId: string,\n {\n concurrency = 3,\n fetchMissingBlocks = true,\n fetchCollections = true,\n signFileUrls = true,\n chunkLimit = 100,\n chunkNumber = 0,\n throwOnCollectionErrors = false,\n collectionReducerLimit = 999,\n fetchRelationPages = false,\n ofetchOptions\n }: {\n concurrency?: number\n fetchMissingBlocks?: boolean\n fetchCollections?: boolean\n signFileUrls?: boolean\n chunkLimit?: number\n chunkNumber?: number\n throwOnCollectionErrors?: boolean\n collectionReducerLimit?: number\n fetchRelationPages?: boolean\n ofetchOptions?: OfetchOptions\n } = {}\n ): Promise<notion.ExtendedRecordMap> {\n const page = await this.getPageRaw(pageId, {\n chunkLimit,\n chunkNumber,\n ofetchOptions\n })\n const recordMap = page?.recordMap as notion.ExtendedRecordMap\n\n if (!recordMap?.block) {\n throw new Error(`Notion page not found \"${uuidToId(pageId)}\"`)\n }\n\n // ensure that all top-level maps exist\n recordMap.collection = recordMap.collection ?? {}\n recordMap.collection_view = recordMap.collection_view ?? {}\n recordMap.notion_user = recordMap.notion_user ?? {}\n\n // additional mappings added for convenience\n // note: these are not native notion objects\n recordMap.collection_query = {}\n recordMap.signed_urls = {}\n\n if (fetchMissingBlocks) {\n while (true) {\n // fetch any missing content blocks\n const pendingBlockIds = getPageContentBlockIds(recordMap).filter(\n id => !recordMap.block[id]\n )\n\n if (!pendingBlockIds.length) {\n break\n }\n\n const newBlocks = await this.getBlocks(\n pendingBlockIds,\n ofetchOptions\n ).then(res => res.recordMap.block)\n\n recordMap.block = { ...recordMap.block, ...newBlocks }\n }\n }\n\n const contentBlockIds = getPageContentBlockIds(recordMap)\n\n // Optionally fetch all data for embedded collections and their associated views.\n // NOTE: We're eagerly fetching *all* data for each collection and all of its views.\n // This is really convenient in order to ensure that all data needed for a given\n // Notion page is readily available for use cases involving server-side rendering\n // and edge caching.\n if (fetchCollections) {\n const allCollectionInstances: Array<{\n collectionId: string\n collectionViewId: string\n spaceId?: string\n }> = contentBlockIds.flatMap(blockId => {\n const block = recordMap.block[blockId]?.value\n const collectionId =\n block &&\n (block.type === 'collection_view' ||\n block.type === 'collection_view_page') &&\n getBlockCollectionId(block, recordMap)\n\n if (collectionId) {\n const spaceId = block?.space_id\n return block.view_ids?.map(collectionViewId => ({\n collectionId,\n collectionViewId,\n spaceId\n }))\n } else {\n return []\n }\n })\n\n // fetch data for all collection view instances\n await pMap(\n allCollectionInstances,\n async collectionInstance => {\n const { collectionId, collectionViewId, spaceId } = collectionInstance\n const collectionView =\n recordMap.collection_view[collectionViewId]?.value\n\n try {\n const collectionData = await this.getCollectionData(\n collectionId,\n collectionViewId,\n collectionView,\n {\n limit: collectionReducerLimit,\n spaceId,\n ofetchOptions\n }\n )\n\n // await fs.writeFile(\n // `${collectionId}-${collectionViewId}.json`,\n // JSON.stringify(collectionData.result, null, 2)\n // )\n\n recordMap.block = {\n ...recordMap.block,\n ...collectionData.recordMap.block\n }\n\n recordMap.collection = {\n ...recordMap.collection,\n ...collectionData.recordMap.collection\n }\n\n recordMap.collection_view = {\n ...recordMap.collection_view,\n ...collectionData.recordMap.collection_view\n }\n\n recordMap.notion_user = {\n ...recordMap.notion_user,\n ...collectionData.recordMap.notion_user\n }\n\n recordMap.collection_query![collectionId] = {\n ...recordMap.collection_query![collectionId],\n [collectionViewId]: (collectionData.result as any)?.reducerResults\n }\n } catch (err: any) {\n // It's possible for public pages to link to private collections,\n // in which case Notion returns a 400 error. This may be that or it\n // may be something else.\n console.warn(\n 'NotionAPI collectionQuery error',\n { pageId, collectionId, collectionViewId },\n err.message\n )\n\n if (throwOnCollectionErrors) {\n throw err\n // throw new Error(\n // `NotionAPI error fetching collectionQuery for page \"${pageId}\" collection \"${collectionId}\" view \"${collectionViewId}\": ${err.message}`,\n // {\n // cause: err\n // }\n // )\n } else {\n console.error(err)\n }\n }\n },\n {\n concurrency\n }\n )\n }\n\n // Optionally fetch signed URLs for any embedded files.\n // NOTE: Similar to collection data, we default to eagerly fetching signed URL info\n // because it is preferable for many use cases as opposed to making these API calls\n // lazily from the client-side.\n if (signFileUrls) {\n await this.addSignedUrls({ recordMap, contentBlockIds, ofetchOptions })\n }\n\n if (fetchRelationPages) {\n const newBlocks = await this.fetchRelationPages(recordMap, ofetchOptions)\n recordMap.block = { ...recordMap.block, ...newBlocks }\n }\n\n return recordMap\n }\n\n fetchRelationPages = async (\n recordMap: notion.ExtendedRecordMap,\n ofetchOptions: OfetchOptions | undefined\n ): Promise<notion.BlockMap> => {\n const maxIterations = 10\n\n for (let i = 0; i < maxIterations; ++i) {\n const relationPageIdsThisIteration = new Set<string>()\n\n for (const blockId of Object.keys(recordMap.block)) {\n const blockValue = recordMap.block[blockId]?.value\n if (\n blockValue?.parent_table === 'collection' &&\n blockValue?.parent_id\n ) {\n const collection = recordMap.collection[blockValue.parent_id]?.value\n if (collection?.schema) {\n const ids = this.extractRelationPageIdsFromBlock(\n blockValue,\n collection.schema\n )\n for (const id of ids) relationPageIdsThisIteration.add(id)\n }\n }\n }\n\n const missingRelationPageIds = Array.from(\n relationPageIdsThisIteration\n ).filter(id => !recordMap.block[id]?.value)\n\n if (!missingRelationPageIds.length) break\n\n try {\n const newBlocks = await this.getBlocks(\n missingRelationPageIds,\n ofetchOptions\n ).then(res => res.recordMap.block)\n recordMap.block = { ...recordMap.block, ...newBlocks }\n } catch (err: any) {\n console.warn(\n 'NotionAPI getBlocks error during fetchRelationPages:',\n err\n )\n // consider break or delay/retry here\n }\n }\n\n return recordMap.block\n }\n\n extractRelationPageIdsFromBlock = (\n blockValue: any,\n collectionSchema: any\n ): Set<string> => {\n const pageIds = new Set<string>()\n\n for (const propertyId of Object.keys(blockValue.properties || {})) {\n const schema = collectionSchema[propertyId]\n if (schema?.type === 'relation') {\n const decorations = blockValue.properties[propertyId]\n if (Array.isArray(decorations)) {\n for (const decoration of decorations) {\n if (\n Array.isArray(decoration) &&\n decoration.length > 1 &&\n decoration[0] === '‣'\n ) {\n const pagePointer = decoration[1]?.[0]\n if (\n Array.isArray(pagePointer) &&\n pagePointer.length > 1 &&\n pagePointer[0] === 'p'\n ) {\n pageIds.add(pagePointer[1])\n }\n }\n }\n }\n }\n }\n return pageIds\n }\n\n public async addSignedUrls({\n recordMap,\n contentBlockIds,\n ofetchOptions = {}\n }: {\n recordMap: notion.ExtendedRecordMap\n contentBlockIds?: string[]\n ofetchOptions?: OfetchOptions\n }) {\n recordMap.signed_urls = {}\n\n if (!contentBlockIds) {\n contentBlockIds = getPageContentBlockIds(recordMap)\n }\n\n const allFileInstances = contentBlockIds.flatMap(blockId => {\n const block = recordMap.block[blockId]?.value\n\n if (\n block &&\n (block.type === 'pdf' ||\n block.type === 'audio' ||\n (block.type === 'image' && block.file_ids?.length) ||\n block.type === 'video' ||\n block.type === 'file' ||\n block.type === 'page')\n ) {\n const source =\n block.type === 'page'\n ? block.format?.page_cover\n : block.properties?.source?.[0]?.[0]\n // console.log(block, source)\n\n if (source) {\n if (\n source.includes('secure.notion-static.com') ||\n source.includes('prod-files-secure') ||\n source.includes('attachment:')\n ) {\n return {\n permissionRecord: {\n table: 'block',\n id: block.id\n },\n url: source\n }\n }\n\n return []\n }\n }\n\n return []\n })\n\n if (allFileInstances.length > 0) {\n try {\n const { signedUrls } = await this.getSignedFileUrls(\n allFileInstances,\n ofetchOptions\n )\n\n if (signedUrls.length === allFileInstances.length) {\n for (const [i, file] of allFileInstances.entries()) {\n const signedUrl = signedUrls[i]\n if (!signedUrl) continue\n\n const blockId = file.permissionRecord.id\n if (!blockId) continue\n\n recordMap.signed_urls[blockId] = signedUrl\n }\n }\n } catch (err) {\n console.warn('NotionAPI getSignedfileUrls error', err)\n }\n }\n }\n\n public async getPageRaw(\n pageId: string,\n {\n ofetchOptions,\n chunkLimit = 100,\n chunkNumber = 0\n }: {\n chunkLimit?: number\n chunkNumber?: number\n ofetchOptions?: OfetchOptions\n } = {}\n ) {\n const parsedPageId = parsePageId(pageId)\n\n if (!parsedPageId) {\n throw new Error(`invalid notion pageId \"${pageId}\"`)\n }\n\n const body = {\n pageId: parsedPageId,\n limit: chunkLimit,\n chunkNumber,\n cursor: { stack: [] },\n verticalColumns: false\n }\n\n return this.fetch<notion.PageChunk>({\n endpoint: 'loadPageChunk',\n body,\n ofetchOptions\n })\n }\n\n public async getCollectionData(\n collectionId: string,\n collectionViewId: string,\n collectionView?: any,\n {\n limit = 999,\n searchQuery = '',\n userTimeZone = this._userTimeZone,\n loadContentCover = true,\n spaceId,\n ofetchOptions\n }: {\n type?: notion.CollectionViewType\n limit?: number\n searchQuery?: string\n userTimeZone?: string\n userLocale?: string\n loadContentCover?: boolean\n spaceId?: string\n ofetchOptions?: OfetchOptions\n } = {}\n ) {\n const type = collectionView?.type\n const isBoardType = type === 'board'\n const groupBy = isBoardType\n ? collectionView?.format?.board_columns_by\n : collectionView?.format?.collection_group_by\n\n let filters = []\n if (collectionView?.format?.property_filters) {\n filters = collectionView.format?.property_filters.map(\n (filterObj: any) => {\n //get the inner filter\n return {\n filter: filterObj?.filter?.filter,\n property: filterObj?.filter?.property\n }\n }\n )\n }\n\n // Fixes formula filters from not working\n if (collectionView?.query2?.filter?.filters) {\n filters.push(...collectionView.query2.filter.filters)\n }\n\n let loader: any = {\n type: 'reducer',\n reducers: {\n collection_group_results: {\n type: 'results',\n limit,\n loadContentCover\n }\n },\n sort: [],\n ...collectionView?.query2,\n filter: {\n filters,\n operator: 'and'\n },\n searchQuery,\n userTimeZone\n }\n\n if (groupBy) {\n const groups =\n collectionView?.format?.board_columns ||\n collectionView?.format?.collection_groups ||\n []\n const iterators = [isBoardType ? 'board' : 'group_aggregation', 'results']\n const operators = {\n checkbox: 'checkbox_is',\n url: 'string_starts_with',\n text: 'string_starts_with',\n select: 'enum_is',\n multi_select: 'enum_contains',\n created_time: 'date_is_within',\n undefined: 'is_empty'\n }\n\n const reducersQuery: Record<string, any> = {}\n for (const group of groups) {\n const {\n property,\n value: { value, type }\n } = group\n\n for (const iterator of iterators) {\n const iteratorProps =\n iterator === 'results'\n ? {\n type: iterator,\n limit\n }\n : {\n type: 'aggregation',\n aggregation: {\n aggregator: 'count'\n }\n }\n\n const isUncategorizedValue = value === undefined\n const isDateValue = value?.range\n // TODO: review dates reducers\n const queryLabel = isUncategorizedValue\n ? 'uncategorized'\n : isDateValue\n ? value.range?.start_date || value.range?.end_date\n : value?.value || value\n\n const queryValue =\n !isUncategorizedValue && (isDateValue || value?.value || value)\n\n reducersQuery[`${iterator}:${type}:${queryLabel}`] = {\n ...iteratorProps,\n filter: {\n operator: 'and',\n filters: [\n {\n property,\n filter: {\n operator: !isUncategorizedValue\n ? operators[type as keyof typeof operators]\n : 'is_empty',\n ...(!isUncategorizedValue && {\n value: {\n type: 'exact',\n value: queryValue\n }\n })\n }\n }\n ]\n }\n }\n }\n }\n\n const reducerLabel = isBoardType ? 'board_columns' : `${type}_groups`\n loader = {\n type: 'reducer',\n reducers: {\n [reducerLabel]: {\n type: 'groups',\n version: 'v2',\n groupBy,\n ...(collectionView?.query2?.filter && {\n filter: collectionView?.query2?.filter\n }),\n groupSortPreference: groups.map((group: any) => ({\n property: group?.property,\n value: {\n type: group?.value?.type,\n value: group?.value?.value\n }\n })),\n limit\n },\n ...reducersQuery\n },\n ...collectionView?.query2,\n searchQuery,\n userTimeZone,\n //TODO: add filters here\n filter: {\n filters,\n operator: 'and'\n }\n }\n }\n\n // if (isBoardType) {\n // console.log(\n // JSON.stringify(\n // {\n // collectionId,\n // collectionViewId,\n // loader,\n // groupBy: groupBy || 'NONE',\n // collectionViewQuery: collectionView.query2 || 'NONE'\n // },\n // null,\n // 2\n // )\n // )\n // }\n\n const headers: any = {}\n if (spaceId) {\n headers['x-notion-space-id'] = spaceId\n }\n\n return this.fetch<notion.CollectionInstance>({\n endpoint: 'queryCollection',\n body: {\n collection: {\n id: collectionId\n },\n collectionView: {\n id: collectionViewId\n },\n source: {\n type: 'collection',\n id: collectionId\n },\n loader\n },\n headers,\n ofetchOptions: {\n timeout: 60_000,\n ...ofetchOptions,\n params: {\n // TODO: spread ofetchOptions?.searchParams\n src: 'initial_load'\n }\n }\n })\n }\n\n public async getUsers(userIds: string[], ofetchOptions?: OfetchOptions) {\n return this.fetch<notion.RecordValues<notion.User>>({\n endpoint: 'getRecordValues',\n body: {\n requests: userIds.map(id => ({ id, table: 'notion_user' }))\n },\n ofetchOptions\n })\n }\n\n public async getBlocks(blockIds: string[], ofetchOptions?: OfetchOptions) {\n return this.fetch<notion.PageChunk>({\n endpoint: 'syncRecordValuesMain',\n body: {\n requests: blockIds.map(blockId => ({\n // TODO: when to use table 'space' vs 'block'?\n table: 'block',\n id: blockId,\n version: -1\n }))\n },\n ofetchOptions\n })\n }\n\n public async getSignedFileUrls(\n urls: types.SignedUrlRequest[],\n ofetchOptions?: OfetchOptions\n ) {\n return this.fetch<types.SignedUrlResponse>({\n endpoint: 'getSignedFileUrls',\n body: {\n urls\n },\n ofetchOptions\n })\n }\n\n public async search(\n params: notion.SearchParams,\n ofetchOptions?: OfetchOptions\n ) {\n const body = {\n type: 'BlocksInAncestor',\n source: 'quick_find_public',\n ancestorId: parsePageId(params.ancestorId),\n sort: {\n field: 'relevance'\n },\n limit: params.limit || 20,\n query: params.query,\n filters: {\n isDeletedOnly: false,\n isNavigableOnly: false,\n excludeTemplates: true,\n requireEditPermissions: false,\n includePublicPagesWithoutExplicitAccess: true,\n ancestors: [],\n createdBy: [],\n editedBy: [],\n lastEditedTime: {},\n createdTime: {},\n ...params.filters\n }\n }\n\n return this.fetch<notion.SearchResults>({\n endpoint: 'search',\n body,\n ofetchOptions\n })\n }\n\n public async fetch<T>({\n endpoint,\n body,\n ofetchOptions,\n headers: clientHeaders\n }: {\n endpoint: string\n body: object\n ofetchOptions?: OfetchOptions\n headers?: any\n }): Promise<T> {\n const headers: any = {\n ...clientHeaders,\n ...this._ofetchOptions?.headers,\n ...ofetchOptions?.headers,\n 'Content-Type': 'application/json'\n }\n\n if (this._authToken) {\n headers.cookie = `token_v2=${this._authToken}`\n }\n\n if (this._activeUser) {\n headers['x-notion-active-user-header'] = this._activeUser\n }\n\n const url = `${this._apiBaseUrl}/${endpoint}`\n\n /* const res = await ky.post(url, {\n mode: 'no-cors',\n ...this._ofetchOptions,\n ...ofetchOptions,\n json: body,\n headers\n }) */\n\n // TODO: we're awaiting the first fetch and then separately awaiting\n // `res.json()` because there seems to be some weird error which repros\n // sporadically when loading collections where the body is already used.\n // No idea why, but from my testing, separating these into two separate\n // steps seems to fix the issue locally for me...\n // console.log(endpoint, { bodyUsed: res.bodyUsed })\n\n /* return res.json<T>() */\n const res = ofetch(url, {\n method: 'POST',\n mode: 'no-cors',\n ...this._ofetchOptions,\n ...ofetchOptions,\n body,\n headers\n })\n return res\n }\n}\n"],"mappings":"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","names":["_a","_b","type"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@slogvo/notion-client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Robust TypeScript client for the unofficial Notion API.",
|
|
6
|
+
"repository": "slogvo/vue-notion",
|
|
7
|
+
"author": "Vue Notion Contributors",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"keywords": [
|
|
10
|
+
"notion",
|
|
11
|
+
"notion-api",
|
|
12
|
+
"client",
|
|
13
|
+
"typescript"
|
|
14
|
+
],
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public",
|
|
17
|
+
"registry": "https://registry.npmjs.org/"
|
|
18
|
+
},
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/slogvo/vue-notion/issues"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/slogvo/vue-notion#readme",
|
|
23
|
+
"main": "./build/index.js",
|
|
24
|
+
"module": "./build/index.js",
|
|
25
|
+
"types": "./build/index.d.ts",
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"files": [
|
|
28
|
+
"build"
|
|
29
|
+
],
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"ofetch": "^1.4.1",
|
|
35
|
+
"p-map": "^7.0.3",
|
|
36
|
+
"@slogvo/notion-types": "0.1.0",
|
|
37
|
+
"@slogvo/notion-utils": "0.1.0"
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "tsup",
|
|
41
|
+
"dev": "tsup --watch",
|
|
42
|
+
"watch": "tsup --watch --silent --onSuccess 'echo build successful'",
|
|
43
|
+
"clean": "del build",
|
|
44
|
+
"test": "run-s test:*",
|
|
45
|
+
"test:lint": "eslint .",
|
|
46
|
+
"test:typecheck": "tsc --noEmit",
|
|
47
|
+
"test:unit": "vitest run"
|
|
48
|
+
}
|
|
49
|
+
}
|