@visus-io/notion-sdk-ts 3.0.2 → 3.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.
Files changed (91) hide show
  1. package/README.md +7 -6
  2. package/dist/api/asyncTasks.api.d.ts +70 -0
  3. package/dist/api/asyncTasks.api.js +68 -0
  4. package/dist/api/base.api.js +1 -0
  5. package/dist/api/blocks.api.d.ts +433 -73
  6. package/dist/api/blocks.api.js +39 -0
  7. package/dist/api/comments.api.d.ts +40 -5
  8. package/dist/api/comments.api.js +43 -1
  9. package/dist/api/customEmojis.api.d.ts +36 -0
  10. package/dist/api/customEmojis.api.js +36 -0
  11. package/dist/api/dataSources.api.d.ts +62 -11
  12. package/dist/api/dataSources.api.js +22 -0
  13. package/dist/api/databases.api.d.ts +40 -6
  14. package/dist/api/fileUploads.api.d.ts +1 -1
  15. package/dist/api/index.d.ts +3 -0
  16. package/dist/api/index.js +7 -1
  17. package/dist/api/pages.api.d.ts +142 -10
  18. package/dist/api/pages.api.js +64 -0
  19. package/dist/api/search.api.d.ts +10 -2
  20. package/dist/api/users.api.d.ts +1 -0
  21. package/dist/api/views.api.d.ts +284 -0
  22. package/dist/api/views.api.js +169 -0
  23. package/dist/client.js +3 -3
  24. package/dist/errors.d.ts +5 -1
  25. package/dist/errors.js +6 -0
  26. package/dist/helpers/block.helpers.d.ts +38 -1
  27. package/dist/helpers/block.helpers.js +45 -3
  28. package/dist/helpers/file.helpers.d.ts +36 -1
  29. package/dist/helpers/file.helpers.js +26 -4
  30. package/dist/helpers/filter.helpers.d.ts +6 -6
  31. package/dist/helpers/index.d.ts +3 -2
  32. package/dist/helpers/index.js +5 -1
  33. package/dist/helpers/pagination.helpers.d.ts +56 -0
  34. package/dist/helpers/pagination.helpers.js +86 -0
  35. package/dist/helpers/property.helpers.d.ts +29 -0
  36. package/dist/helpers/property.helpers.js +27 -0
  37. package/dist/helpers/webhook.helpers.d.ts +52 -0
  38. package/dist/helpers/webhook.helpers.js +81 -0
  39. package/dist/models/asyncTask.model.d.ts +59 -0
  40. package/dist/models/asyncTask.model.js +89 -0
  41. package/dist/models/block.model.js +4 -1
  42. package/dist/models/customEmoji.model.d.ts +28 -0
  43. package/dist/models/customEmoji.model.js +42 -0
  44. package/dist/models/dataSource.model.d.ts +3 -3
  45. package/dist/models/dataSource.model.js +1 -1
  46. package/dist/models/database.model.d.ts +7 -3
  47. package/dist/models/database.model.js +7 -1
  48. package/dist/models/index.d.ts +3 -0
  49. package/dist/models/index.js +7 -1
  50. package/dist/models/page.model.d.ts +2 -0
  51. package/dist/models/page.model.js +6 -0
  52. package/dist/models/view.model.d.ts +79 -0
  53. package/dist/models/view.model.js +119 -0
  54. package/dist/notion.d.ts +26 -7
  55. package/dist/notion.js +19 -3
  56. package/dist/schemas/asyncTask.schema.d.ts +42 -0
  57. package/dist/schemas/asyncTask.schema.js +83 -0
  58. package/dist/schemas/block.schema.d.ts +378 -72
  59. package/dist/schemas/block.schema.js +33 -7
  60. package/dist/schemas/comment.schema.d.ts +8 -3
  61. package/dist/schemas/customEmoji.schema.d.ts +13 -0
  62. package/dist/schemas/customEmoji.schema.js +48 -0
  63. package/dist/schemas/dataSource.schema.d.ts +68 -10
  64. package/dist/schemas/dataSource.schema.js +22 -4
  65. package/dist/schemas/database.schema.d.ts +38 -6
  66. package/dist/schemas/database.schema.js +3 -2
  67. package/dist/schemas/fileUpload.schema.d.ts +1 -1
  68. package/dist/schemas/icon.schema.d.ts +92 -0
  69. package/dist/schemas/icon.schema.js +88 -0
  70. package/dist/schemas/index.d.ts +6 -0
  71. package/dist/schemas/index.js +6 -0
  72. package/dist/schemas/meetingNotesQuery.schema.d.ts +4187 -0
  73. package/dist/schemas/meetingNotesQuery.schema.js +62 -0
  74. package/dist/schemas/page.schema.d.ts +46 -9
  75. package/dist/schemas/page.schema.js +4 -2
  76. package/dist/schemas/pageMarkdown.schema.d.ts +59 -0
  77. package/dist/schemas/pageMarkdown.schema.js +65 -0
  78. package/dist/schemas/pageProperties.schema.d.ts +30 -18
  79. package/dist/schemas/pageProperties.schema.js +2 -3
  80. package/dist/schemas/pagination.schema.d.ts +30 -3
  81. package/dist/schemas/pagination.schema.js +18 -1
  82. package/dist/schemas/parent.schema.d.ts +10 -1
  83. package/dist/schemas/parent.schema.js +9 -3
  84. package/dist/schemas/propertyObjects.schema.d.ts +12 -12
  85. package/dist/schemas/richText.schema.d.ts +8 -6
  86. package/dist/schemas/richText.schema.js +1 -1
  87. package/dist/schemas/user.schema.d.ts +2 -0
  88. package/dist/schemas/user.schema.js +2 -1
  89. package/dist/schemas/view.schema.d.ts +1077 -0
  90. package/dist/schemas/view.schema.js +115 -0
  91. package/package.json +2 -2
@@ -8,13 +8,21 @@ import { DataSource, Page } from '../models';
8
8
  export type SearchFilterObject = 'page' | 'data_source';
9
9
  /**
10
10
  * Search filter configuration.
11
+ *
12
+ * `in_trash` can be combined with the object filter (`property`/`value`) or
13
+ * used on its own to list only trashed content.
11
14
  */
12
- export interface SearchFilter {
15
+ export type SearchFilter = {
13
16
  /** Filter by object type */
14
17
  value: SearchFilterObject;
15
18
  /** Property to filter on (always "object" for this filter type) */
16
19
  property: 'object';
17
- }
20
+ /** Whether to list only trashed pages and data sources */
21
+ in_trash?: boolean;
22
+ } | {
23
+ /** Whether to list only trashed pages and data sources */
24
+ in_trash: boolean;
25
+ };
18
26
  /**
19
27
  * Search sort configuration.
20
28
  */
@@ -16,6 +16,7 @@ export declare class UsersAPI extends BaseAPI<NotionUser, User> {
16
16
  avatar_url: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodURL, import("zod").ZodNull]>>;
17
17
  person: import("zod").ZodObject<{
18
18
  email: import("zod").ZodEmail;
19
+ email_verified: import("zod").ZodOptional<import("zod").ZodBoolean>;
19
20
  }, import("zod/v4/core").$strip>;
20
21
  }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
21
22
  object: import("zod").ZodLiteral<"user">;
@@ -0,0 +1,284 @@
1
+ import type { NotionClient } from '../client';
2
+ import { Page, View } from '../models';
3
+ import { type NotionView, type PaginatedList, type PaginationParameters, type RequestStatus, type ViewDeleteResult, type ViewType } from '../schemas';
4
+ import { BaseAPI } from './base.api';
5
+ import type { DataSourceSort } from './dataSources.api';
6
+ /**
7
+ * Options for listing views. Exactly one of `database_id`/`data_source_id` must be provided.
8
+ */
9
+ export interface ListViewsOptions extends PaginationParameters {
10
+ /** List views for this database (mutually exclusive with data_source_id) */
11
+ database_id?: string;
12
+ /** List views for this data source (mutually exclusive with database_id) */
13
+ data_source_id?: string;
14
+ }
15
+ /**
16
+ * Options for creating a view. Exactly one of `database_id`/`view_id`/`create_database`
17
+ * must be provided to select the parent context.
18
+ */
19
+ export interface CreateViewOptions {
20
+ /** The data source the view displays */
21
+ data_source_id: string;
22
+ /** The view name */
23
+ name: string;
24
+ /** The view layout type */
25
+ type: ViewType;
26
+ /** Attach the view to this existing database */
27
+ database_id?: string;
28
+ /** Clone the configuration of this existing view */
29
+ view_id?: string;
30
+ /** Create a new database to hold the view */
31
+ create_database?: true;
32
+ /** Filter configuration */
33
+ filter?: Record<string, unknown>;
34
+ /** Sort configuration */
35
+ sorts?: DataSourceSort[];
36
+ /** Quick filter configuration */
37
+ quick_filters?: Record<string, unknown>;
38
+ /** Per-layout configuration */
39
+ configuration?: Record<string, unknown>;
40
+ /** Where to place the new view relative to existing views */
41
+ position?: Record<string, unknown>;
42
+ }
43
+ /**
44
+ * Options for updating a view. All fields optional; passing `null` for
45
+ * filter/sorts/quick_filters clears the existing value.
46
+ */
47
+ export interface UpdateViewOptions {
48
+ /** Rename the view */
49
+ name?: string;
50
+ /** Update or clear (`null`) the filter configuration */
51
+ filter?: Record<string, unknown> | null;
52
+ /** Update or clear (`null`) the sort configuration */
53
+ sorts?: DataSourceSort[] | null;
54
+ /** Update or clear (`null`) the quick filter configuration */
55
+ quick_filters?: Record<string, unknown> | null;
56
+ /** Shallow-merged per-layout configuration update */
57
+ configuration?: Record<string, unknown>;
58
+ }
59
+ /**
60
+ * Options for creating a view query.
61
+ */
62
+ export interface CreateViewQueryOptions extends PaginationParameters {
63
+ /** Filter configuration */
64
+ filter?: Record<string, unknown>;
65
+ /** Sort configuration */
66
+ sorts?: DataSourceSort[];
67
+ }
68
+ /**
69
+ * Result of a view query. Non-standard pagination shape distinct from
70
+ * {@link PaginatedList} -- includes `totalCount` and an `expiresAt` after which the
71
+ * query can no longer be retrieved via {@link ViewsAPI.queries.get}.
72
+ */
73
+ export interface ViewQueryResult {
74
+ id: string;
75
+ viewId: string;
76
+ expiresAt: Date;
77
+ totalCount: number;
78
+ results: Page[];
79
+ nextCursor: string | null;
80
+ hasMore: boolean;
81
+ requestStatus?: RequestStatus;
82
+ }
83
+ /**
84
+ * Views API client for working with Notion views.
85
+ *
86
+ * Views control how a database/data source's rows are displayed (table, board,
87
+ * calendar, etc.). Requires API version 2025-09-03 or later.
88
+ */
89
+ export declare class ViewsAPI extends BaseAPI<NotionView, View> {
90
+ protected readonly client: NotionClient;
91
+ protected config: {
92
+ schema: import("zod").ZodObject<{
93
+ object: import("zod").ZodLiteral<"view">;
94
+ id: import("zod").ZodUUID;
95
+ parent: import("zod").ZodObject<{
96
+ type: import("zod").ZodLiteral<"database_id">;
97
+ database_id: import("zod").ZodUUID;
98
+ }, import("zod/v4/core").$strip>;
99
+ data_source_id: import("zod").ZodNullable<import("zod").ZodUUID>;
100
+ name: import("zod").ZodString;
101
+ type: import("zod").ZodEnum<{
102
+ map: "map";
103
+ table: "table";
104
+ list: "list";
105
+ board: "board";
106
+ calendar: "calendar";
107
+ timeline: "timeline";
108
+ gallery: "gallery";
109
+ form: "form";
110
+ chart: "chart";
111
+ dashboard: "dashboard";
112
+ }>;
113
+ filter: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>>;
114
+ sorts: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodArray<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>>>;
115
+ quick_filters: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>>>;
116
+ configuration: import("zod").ZodOptional<import("zod").ZodObject<{
117
+ type: import("zod").ZodEnum<{
118
+ map: "map";
119
+ table: "table";
120
+ list: "list";
121
+ board: "board";
122
+ calendar: "calendar";
123
+ timeline: "timeline";
124
+ gallery: "gallery";
125
+ form: "form";
126
+ chart: "chart";
127
+ dashboard: "dashboard";
128
+ }>;
129
+ }, import("zod/v4/core").$catchall<import("zod").ZodUnknown>>>;
130
+ created_time: import("zod").ZodUnion<readonly [import("zod").ZodISODateTime, import("zod").ZodISODate]>;
131
+ last_edited_time: import("zod").ZodUnion<readonly [import("zod").ZodISODateTime, import("zod").ZodISODate]>;
132
+ created_by: import("zod").ZodUnion<readonly [import("zod").ZodObject<{
133
+ object: import("zod").ZodLiteral<"user">;
134
+ id: import("zod").ZodUUID;
135
+ type: import("zod").ZodLiteral<"person">;
136
+ name: import("zod").ZodOptional<import("zod").ZodString>;
137
+ avatar_url: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodURL, import("zod").ZodNull]>>;
138
+ person: import("zod").ZodObject<{
139
+ email: import("zod").ZodEmail;
140
+ email_verified: import("zod").ZodOptional<import("zod").ZodBoolean>;
141
+ }, import("zod/v4/core").$strip>;
142
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
143
+ object: import("zod").ZodLiteral<"user">;
144
+ id: import("zod").ZodUUID;
145
+ type: import("zod").ZodLiteral<"bot">;
146
+ name: import("zod").ZodOptional<import("zod").ZodString>;
147
+ avatar_url: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodURL, import("zod").ZodNull]>>;
148
+ bot: import("zod").ZodObject<{
149
+ owner: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
150
+ type: import("zod").ZodLiteral<"workspace">;
151
+ workspace: import("zod").ZodLiteral<true>;
152
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
153
+ type: import("zod").ZodLiteral<"user">;
154
+ }, import("zod/v4/core").$strip>], "type">;
155
+ workspace_name: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
156
+ workspace_id: import("zod").ZodOptional<import("zod").ZodString>;
157
+ workspace_limits: import("zod").ZodOptional<import("zod").ZodObject<{
158
+ max_file_upload_size_in_bytes: import("zod").ZodInt;
159
+ }, import("zod/v4/core").$strip>>;
160
+ }, import("zod/v4/core").$strip>;
161
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
162
+ object: import("zod").ZodLiteral<"user">;
163
+ id: import("zod").ZodUUID;
164
+ }, import("zod/v4/core").$strip>]>;
165
+ last_edited_by: import("zod").ZodUnion<readonly [import("zod").ZodObject<{
166
+ object: import("zod").ZodLiteral<"user">;
167
+ id: import("zod").ZodUUID;
168
+ type: import("zod").ZodLiteral<"person">;
169
+ name: import("zod").ZodOptional<import("zod").ZodString>;
170
+ avatar_url: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodURL, import("zod").ZodNull]>>;
171
+ person: import("zod").ZodObject<{
172
+ email: import("zod").ZodEmail;
173
+ email_verified: import("zod").ZodOptional<import("zod").ZodBoolean>;
174
+ }, import("zod/v4/core").$strip>;
175
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
176
+ object: import("zod").ZodLiteral<"user">;
177
+ id: import("zod").ZodUUID;
178
+ type: import("zod").ZodLiteral<"bot">;
179
+ name: import("zod").ZodOptional<import("zod").ZodString>;
180
+ avatar_url: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodURL, import("zod").ZodNull]>>;
181
+ bot: import("zod").ZodObject<{
182
+ owner: import("zod").ZodDiscriminatedUnion<[import("zod").ZodObject<{
183
+ type: import("zod").ZodLiteral<"workspace">;
184
+ workspace: import("zod").ZodLiteral<true>;
185
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
186
+ type: import("zod").ZodLiteral<"user">;
187
+ }, import("zod/v4/core").$strip>], "type">;
188
+ workspace_name: import("zod").ZodOptional<import("zod").ZodNullable<import("zod").ZodString>>;
189
+ workspace_id: import("zod").ZodOptional<import("zod").ZodString>;
190
+ workspace_limits: import("zod").ZodOptional<import("zod").ZodObject<{
191
+ max_file_upload_size_in_bytes: import("zod").ZodInt;
192
+ }, import("zod/v4/core").$strip>>;
193
+ }, import("zod/v4/core").$strip>;
194
+ }, import("zod/v4/core").$strip>, import("zod").ZodObject<{
195
+ object: import("zod").ZodLiteral<"user">;
196
+ id: import("zod").ZodUUID;
197
+ }, import("zod/v4/core").$strip>]>;
198
+ url: import("zod").ZodURL;
199
+ dashboard_view_id: import("zod").ZodOptional<import("zod").ZodUUID>;
200
+ }, import("zod/v4/core").$strip>;
201
+ ModelClass: typeof View;
202
+ listType: "view";
203
+ };
204
+ constructor(client: NotionClient);
205
+ /**
206
+ * List the views for a database or data source.
207
+ *
208
+ * @param options - Exactly one of `database_id`/`data_source_id`, plus pagination
209
+ * @returns Paginated list of views
210
+ *
211
+ * @throws {NotionValidationError} If neither or both of `database_id`/`data_source_id` are provided
212
+ *
213
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
214
+ */
215
+ list(options: ListViewsOptions): Promise<PaginatedList<View>>;
216
+ /**
217
+ * Retrieve a view by ID.
218
+ *
219
+ * @param viewId - The ID of the view to retrieve
220
+ * @returns The view wrapped in a View model
221
+ *
222
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
223
+ */
224
+ retrieve(viewId: string): Promise<View>;
225
+ /**
226
+ * Create a new view.
227
+ *
228
+ * @param options - Options for creating the view
229
+ * @returns The created view wrapped in a View model
230
+ *
231
+ * @throws {NotionValidationError} If not exactly one of `database_id`/`view_id`/`create_database` is provided
232
+ *
233
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
234
+ */
235
+ create(options: CreateViewOptions): Promise<View>;
236
+ /**
237
+ * Update a view's name, filter, sorts, quick filters, or configuration.
238
+ *
239
+ * @param viewId - The ID of the view to update
240
+ * @param options - Options for updating the view
241
+ * @returns The updated view wrapped in a View model
242
+ *
243
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
244
+ */
245
+ update(viewId: string, options: UpdateViewOptions): Promise<View>;
246
+ /**
247
+ * Delete a view.
248
+ *
249
+ * Note: unlike other delete methods, Notion's delete-view response only includes
250
+ * `object`/`id`/`parent`/`type` (not the full view shape), so this returns the raw
251
+ * parsed result rather than a full {@link View} model.
252
+ *
253
+ * @param viewId - The ID of the view to delete
254
+ * @returns The partial view object returned by the API
255
+ *
256
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
257
+ */
258
+ delete(viewId: string): Promise<ViewDeleteResult>;
259
+ /**
260
+ * Sub-resource for querying a view's rows. View queries are non-standard: they
261
+ * return a `total_count` and `expires_at`, and the query result itself expires
262
+ * roughly 15 minutes after creation.
263
+ */
264
+ readonly queries: {
265
+ /**
266
+ * Create a new query against a view.
267
+ *
268
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
269
+ */
270
+ create: (viewId: string, options?: CreateViewQueryOptions) => Promise<ViewQueryResult>;
271
+ /**
272
+ * Retrieve the results of a previously created view query.
273
+ *
274
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
275
+ */
276
+ get: (viewId: string, queryId: string) => Promise<ViewQueryResult>;
277
+ /**
278
+ * Delete a view query.
279
+ *
280
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
281
+ */
282
+ delete: (viewId: string, queryId: string) => Promise<void>;
283
+ };
284
+ }
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ViewsAPI = void 0;
4
+ const models_1 = require("../models");
5
+ const schemas_1 = require("../schemas");
6
+ const validation_1 = require("../validation");
7
+ const base_api_1 = require("./base.api");
8
+ function toViewQueryResult(response) {
9
+ const parsed = schemas_1.viewQueryResponseSchema.parse(response);
10
+ return {
11
+ id: parsed.id,
12
+ viewId: parsed.view_id,
13
+ expiresAt: new Date(parsed.expires_at),
14
+ totalCount: parsed.total_count,
15
+ results: parsed.results.map((page) => new models_1.Page(page)),
16
+ nextCursor: parsed.next_cursor,
17
+ hasMore: parsed.has_more,
18
+ requestStatus: parsed.request_status,
19
+ };
20
+ }
21
+ /**
22
+ * Views API client for working with Notion views.
23
+ *
24
+ * Views control how a database/data source's rows are displayed (table, board,
25
+ * calendar, etc.). Requires API version 2025-09-03 or later.
26
+ */
27
+ class ViewsAPI extends base_api_1.BaseAPI {
28
+ constructor(client) {
29
+ super(client);
30
+ this.client = client;
31
+ this.config = {
32
+ schema: schemas_1.viewSchema,
33
+ ModelClass: models_1.View,
34
+ listType: 'view',
35
+ };
36
+ /**
37
+ * Sub-resource for querying a view's rows. View queries are non-standard: they
38
+ * return a `total_count` and `expires_at`, and the query result itself expires
39
+ * roughly 15 minutes after creation.
40
+ */
41
+ this.queries = {
42
+ /**
43
+ * Create a new query against a view.
44
+ *
45
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
46
+ */
47
+ create: async (viewId, options) => {
48
+ const body = {};
49
+ if (options?.filter) {
50
+ body.filter = options.filter;
51
+ }
52
+ if (options?.sorts) {
53
+ body.sorts = options.sorts;
54
+ }
55
+ Object.assign(body, this.buildPaginationBody(options));
56
+ const response = await this.client.request({
57
+ method: 'POST',
58
+ path: `/views/${viewId}/queries`,
59
+ body: Object.keys(body).length > 0 ? body : undefined,
60
+ });
61
+ return toViewQueryResult(response);
62
+ },
63
+ /**
64
+ * Retrieve the results of a previously created view query.
65
+ *
66
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
67
+ */
68
+ get: async (viewId, queryId) => {
69
+ const response = await this.client.request({
70
+ method: 'GET',
71
+ path: `/views/${viewId}/queries/${queryId}`,
72
+ });
73
+ return toViewQueryResult(response);
74
+ },
75
+ /**
76
+ * Delete a view query.
77
+ *
78
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
79
+ */
80
+ delete: async (viewId, queryId) => {
81
+ await this.client.request({
82
+ method: 'DELETE',
83
+ path: `/views/${viewId}/queries/${queryId}`,
84
+ });
85
+ },
86
+ };
87
+ }
88
+ /**
89
+ * List the views for a database or data source.
90
+ *
91
+ * @param options - Exactly one of `database_id`/`data_source_id`, plus pagination
92
+ * @returns Paginated list of views
93
+ *
94
+ * @throws {NotionValidationError} If neither or both of `database_id`/`data_source_id` are provided
95
+ *
96
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
97
+ */
98
+ async list(options) {
99
+ if (Boolean(options.database_id) === Boolean(options.data_source_id)) {
100
+ throw new validation_1.NotionValidationError('Exactly one of database_id or data_source_id must be provided');
101
+ }
102
+ const query = {
103
+ ...(options.database_id ? { database_id: options.database_id } : {}),
104
+ ...(options.data_source_id ? { data_source_id: options.data_source_id } : {}),
105
+ ...this.buildPaginationQuery(options),
106
+ };
107
+ return this.listResources('/views', query);
108
+ }
109
+ /**
110
+ * Retrieve a view by ID.
111
+ *
112
+ * @param viewId - The ID of the view to retrieve
113
+ * @returns The view wrapped in a View model
114
+ *
115
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
116
+ */
117
+ async retrieve(viewId) {
118
+ return this.retrieveResource(`/views/${viewId}`);
119
+ }
120
+ /**
121
+ * Create a new view.
122
+ *
123
+ * @param options - Options for creating the view
124
+ * @returns The created view wrapped in a View model
125
+ *
126
+ * @throws {NotionValidationError} If not exactly one of `database_id`/`view_id`/`create_database` is provided
127
+ *
128
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
129
+ */
130
+ async create(options) {
131
+ const selectorCount = [options.database_id, options.view_id, options.create_database].filter((value) => value !== undefined).length;
132
+ if (selectorCount !== 1) {
133
+ throw new validation_1.NotionValidationError('Exactly one of database_id, view_id, or create_database must be provided');
134
+ }
135
+ return this.createResource('/views', options);
136
+ }
137
+ /**
138
+ * Update a view's name, filter, sorts, quick filters, or configuration.
139
+ *
140
+ * @param viewId - The ID of the view to update
141
+ * @param options - Options for updating the view
142
+ * @returns The updated view wrapped in a View model
143
+ *
144
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
145
+ */
146
+ async update(viewId, options) {
147
+ return this.updateResource(`/views/${viewId}`, options);
148
+ }
149
+ /**
150
+ * Delete a view.
151
+ *
152
+ * Note: unlike other delete methods, Notion's delete-view response only includes
153
+ * `object`/`id`/`parent`/`type` (not the full view shape), so this returns the raw
154
+ * parsed result rather than a full {@link View} model.
155
+ *
156
+ * @param viewId - The ID of the view to delete
157
+ * @returns The partial view object returned by the API
158
+ *
159
+ * @see https://developers.notion.com/guides/data-apis/working-with-views
160
+ */
161
+ async delete(viewId) {
162
+ const response = await this.client.request({
163
+ method: 'DELETE',
164
+ path: `/views/${viewId}`,
165
+ });
166
+ return schemas_1.viewDeleteResponseSchema.parse(response);
167
+ }
168
+ }
169
+ exports.ViewsAPI = ViewsAPI;
package/dist/client.js CHANGED
@@ -29,10 +29,10 @@ class NotionClient {
29
29
  return await this.makeRequest(options);
30
30
  }
31
31
  catch (error) {
32
- // Only retry on rate limit errors if retry is enabled
32
+ // Retry rate-limited requests (if enabled) and service-overload (529)
33
+ // responses, which the API recommends always retrying.
33
34
  if (error instanceof errors_1.NotionAPIError &&
34
- error.isRateLimited() &&
35
- this.retryOnRateLimit &&
35
+ ((error.isRateLimited() && this.retryOnRateLimit) || error.isServiceOverloaded()) &&
36
36
  attempt < this.maxRetries) {
37
37
  // Prefer the server-supplied Retry-After value; fall back to
38
38
  // exponential backoff when the header is absent.
package/dist/errors.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Notion API error codes based on official documentation.
3
3
  */
4
- export type NotionErrorCode = 'invalid_json' | 'invalid_request_url' | 'invalid_request' | 'validation_error' | 'missing_version' | 'unauthorized' | 'restricted_resource' | 'object_not_found' | 'conflict_error' | 'rate_limited' | 'internal_server_error' | 'service_unavailable' | 'database_connection_unavailable' | 'gateway_timeout';
4
+ export type NotionErrorCode = 'invalid_json' | 'invalid_request_url' | 'invalid_request' | 'validation_error' | 'missing_version' | 'unauthorized' | 'restricted_resource' | 'object_not_found' | 'conflict_error' | 'rate_limited' | 'internal_server_error' | 'service_unavailable' | 'service_overload' | 'database_connection_unavailable' | 'gateway_timeout';
5
5
  /**
6
6
  * Notion API error response structure.
7
7
  */
@@ -24,6 +24,10 @@ export declare class NotionAPIError extends Error {
24
24
  * Check if the error is a rate limit error.
25
25
  */
26
26
  isRateLimited(): boolean;
27
+ /**
28
+ * Check if the error is a service overload error (HTTP 529).
29
+ */
30
+ isServiceOverloaded(): boolean;
27
31
  /**
28
32
  * Check if the error is an authentication error.
29
33
  */
package/dist/errors.js CHANGED
@@ -23,6 +23,12 @@ class NotionAPIError extends Error {
23
23
  isRateLimited() {
24
24
  return this.code === 'rate_limited';
25
25
  }
26
+ /**
27
+ * Check if the error is a service overload error (HTTP 529).
28
+ */
29
+ isServiceOverloaded() {
30
+ return this.code === 'service_overload';
31
+ }
26
32
  /**
27
33
  * Check if the error is an authentication error.
28
34
  */
@@ -16,6 +16,11 @@ interface BlockObject {
16
16
  type: string;
17
17
  [key: string]: unknown;
18
18
  }
19
+ /** Options for paragraph blocks. */
20
+ interface ParagraphOptions extends TextBlockOptions {
21
+ /** Icon shown alongside the paragraph. Only meaningful for paragraphs used as tab items. */
22
+ icon?: unknown;
23
+ }
19
24
  /**
20
25
  * Create a paragraph block.
21
26
  *
@@ -25,7 +30,7 @@ interface BlockObject {
25
30
  * block.paragraph(richText('Hello').bold(), { color: 'blue' })
26
31
  * ```
27
32
  */
28
- declare function paragraph(text: RichTextInput, options?: TextBlockOptions): BlockObject;
33
+ declare function paragraph(text: RichTextInput, options?: ParagraphOptions): BlockObject;
29
34
  /** Options for heading blocks. */
30
35
  interface HeadingOptions {
31
36
  color?: NotionColor;
@@ -35,6 +40,7 @@ interface HeadingOptions {
35
40
  declare function heading1(text: RichTextInput, options?: HeadingOptions): BlockObject;
36
41
  declare function heading2(text: RichTextInput, options?: HeadingOptions): BlockObject;
37
42
  declare function heading3(text: RichTextInput, options?: HeadingOptions): BlockObject;
43
+ declare function heading4(text: RichTextInput, options?: HeadingOptions): BlockObject;
38
44
  declare function bulletedListItem(text: RichTextInput, options?: TextBlockOptions): BlockObject;
39
45
  /** Options for numbered list items. */
40
46
  interface NumberedListOptions extends TextBlockOptions {
@@ -65,6 +71,14 @@ declare function callout(text: RichTextInput, options?: CalloutOptions): BlockOb
65
71
  declare function template(text: RichTextInput, options?: {
66
72
  children?: unknown[];
67
73
  }): BlockObject;
74
+ /**
75
+ * @deprecated Meeting-notes blocks are server-managed -- their real shape (`title`,
76
+ * `status`, and child block IDs for the summary/notes/transcript) is populated by
77
+ * Notion, not hand-constructed by clients. This helper's `rich_text`-based output no
78
+ * longer matches `blockSchema`'s `meeting_notes` shape and is not a valid way to
79
+ * create a meeting-notes block. Kept only to avoid an abrupt removal from the helper
80
+ * surface; do not use for new code.
81
+ */
68
82
  declare function meetingNotes(text: RichTextInput, options?: {
69
83
  children?: unknown[];
70
84
  }): BlockObject;
@@ -115,6 +129,27 @@ declare function table(width: number, options?: TableOptions): BlockObject;
115
129
  declare function tableRow(cells: RichTextInput[]): BlockObject;
116
130
  declare function columnList(columns: unknown[][]): BlockObject;
117
131
  declare function column(children: unknown[]): BlockObject;
132
+ /** A single tab: its label becomes the tab's paragraph rich text, `children` its content. */
133
+ interface TabItem {
134
+ label: RichTextInput;
135
+ icon?: unknown;
136
+ color?: NotionColor;
137
+ children?: unknown[];
138
+ }
139
+ /**
140
+ * Create a tab block. Only `paragraph` blocks may be direct children of a tab block --
141
+ * each tab is modeled as one paragraph, whose rich text is the tab label and whose
142
+ * `children` hold the tab's content.
143
+ *
144
+ * @example
145
+ * ```ts
146
+ * block.tab([
147
+ * { label: 'Overview', children: [block.paragraph('Intro text')] },
148
+ * { label: 'Details', icon: icon.emoji('📋'), children: [block.paragraph('More info')] },
149
+ * ])
150
+ * ```
151
+ */
152
+ declare function tab(tabs: TabItem[]): BlockObject;
118
153
  /**
119
154
  * Create a synced block.
120
155
  *
@@ -160,6 +195,7 @@ export declare const block: {
160
195
  heading1: typeof heading1;
161
196
  heading2: typeof heading2;
162
197
  heading3: typeof heading3;
198
+ heading4: typeof heading4;
163
199
  bulletedListItem: typeof bulletedListItem;
164
200
  numberedListItem: typeof numberedListItem;
165
201
  toDo: typeof toDo;
@@ -185,6 +221,7 @@ export declare const block: {
185
221
  tableRow: typeof tableRow;
186
222
  columnList: typeof columnList;
187
223
  column: typeof column;
224
+ tab: typeof tab;
188
225
  syncedBlock: typeof syncedBlock;
189
226
  };
190
227
  export {};