@notionhq/custom-blocks 0.0.58

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 (298) hide show
  1. package/HOST.md +171 -0
  2. package/README.md +57 -0
  3. package/bin/cli/attach.js +180 -0
  4. package/bin/cli/cli.js +248 -0
  5. package/bin/cli/create.js +106 -0
  6. package/bin/cli/datasources.js +255 -0
  7. package/bin/cli/deploy.js +109 -0
  8. package/bin/cli/ids.js +13 -0
  9. package/bin/cli/ntn.js +95 -0
  10. package/bin/cli/pullData.js +76 -0
  11. package/bin/cli/pullManifest.js +158 -0
  12. package/bin/cli/target.js +95 -0
  13. package/bin/src/bridge/dataSources/propertySchema.js +148 -0
  14. package/bin/src/bridge/manifest.js +40 -0
  15. package/dist/autoResize.d.ts +4 -0
  16. package/dist/autoResize.d.ts.map +1 -0
  17. package/dist/autoResize.js +71 -0
  18. package/dist/bridge/SandboxBridge.d.ts +92 -0
  19. package/dist/bridge/SandboxBridge.d.ts.map +1 -0
  20. package/dist/bridge/SandboxBridge.js +718 -0
  21. package/dist/bridge/dataSources/dataSource.d.ts +732 -0
  22. package/dist/bridge/dataSources/dataSource.d.ts.map +1 -0
  23. package/dist/bridge/dataSources/dataSource.js +37 -0
  24. package/dist/bridge/dataSources/dataSourcePage.d.ts +118 -0
  25. package/dist/bridge/dataSources/dataSourcePage.d.ts.map +1 -0
  26. package/dist/bridge/dataSources/dataSourcePage.js +14 -0
  27. package/dist/bridge/dataSources/dataSourceValue.d.ts +67 -0
  28. package/dist/bridge/dataSources/dataSourceValue.d.ts.map +1 -0
  29. package/dist/bridge/dataSources/dataSourceValue.js +14 -0
  30. package/dist/bridge/dataSources/dateValue.d.ts +158 -0
  31. package/dist/bridge/dataSources/dateValue.d.ts.map +1 -0
  32. package/dist/bridge/dataSources/dateValue.js +59 -0
  33. package/dist/bridge/dataSources/errors.d.ts +6 -0
  34. package/dist/bridge/dataSources/errors.d.ts.map +1 -0
  35. package/dist/bridge/dataSources/errors.js +4 -0
  36. package/dist/bridge/dataSources/propertySchema.d.ts +191 -0
  37. package/dist/bridge/dataSources/propertySchema.d.ts.map +1 -0
  38. package/dist/bridge/dataSources/propertySchema.js +148 -0
  39. package/dist/bridge/dataSources/recordPointer.d.ts +10 -0
  40. package/dist/bridge/dataSources/recordPointer.d.ts.map +1 -0
  41. package/dist/bridge/dataSources/recordPointer.js +8 -0
  42. package/dist/bridge/dataSources/resolve.d.ts +22 -0
  43. package/dist/bridge/dataSources/resolve.d.ts.map +1 -0
  44. package/dist/bridge/dataSources/resolve.js +65 -0
  45. package/dist/bridge/dataSources/resolveProperty.d.ts +41 -0
  46. package/dist/bridge/dataSources/resolveProperty.d.ts.map +1 -0
  47. package/dist/bridge/dataSources/resolveProperty.js +73 -0
  48. package/dist/bridge/errors.d.ts +12 -0
  49. package/dist/bridge/errors.d.ts.map +1 -0
  50. package/dist/bridge/errors.js +6 -0
  51. package/dist/bridge/hostState.d.ts +65 -0
  52. package/dist/bridge/hostState.d.ts.map +1 -0
  53. package/dist/bridge/hostState.js +65 -0
  54. package/dist/bridge/ids.d.ts +39 -0
  55. package/dist/bridge/ids.d.ts.map +1 -0
  56. package/dist/bridge/ids.js +5 -0
  57. package/dist/bridge/incomingType.d.ts +10 -0
  58. package/dist/bridge/incomingType.d.ts.map +1 -0
  59. package/dist/bridge/incomingType.js +17 -0
  60. package/dist/bridge/loadManifest.d.ts +25 -0
  61. package/dist/bridge/loadManifest.d.ts.map +1 -0
  62. package/dist/bridge/loadManifest.js +68 -0
  63. package/dist/bridge/manifest.d.ts +66 -0
  64. package/dist/bridge/manifest.d.ts.map +1 -0
  65. package/dist/bridge/manifest.js +40 -0
  66. package/dist/bridge/messages/createPage.d.ts +225 -0
  67. package/dist/bridge/messages/createPage.d.ts.map +1 -0
  68. package/dist/bridge/messages/createPage.js +46 -0
  69. package/dist/bridge/messages/createPageResult.d.ts +211 -0
  70. package/dist/bridge/messages/createPageResult.d.ts.map +1 -0
  71. package/dist/bridge/messages/createPageResult.js +28 -0
  72. package/dist/bridge/messages/currentUserChanged.d.ts +19 -0
  73. package/dist/bridge/messages/currentUserChanged.d.ts.map +1 -0
  74. package/dist/bridge/messages/currentUserChanged.js +9 -0
  75. package/dist/bridge/messages/dataSourcesChanged.d.ts +158 -0
  76. package/dist/bridge/messages/dataSourcesChanged.d.ts.map +1 -0
  77. package/dist/bridge/messages/dataSourcesChanged.js +13 -0
  78. package/dist/bridge/messages/getPage.d.ts +216 -0
  79. package/dist/bridge/messages/getPage.d.ts.map +1 -0
  80. package/dist/bridge/messages/getPage.js +33 -0
  81. package/dist/bridge/messages/getUser.d.ts +45 -0
  82. package/dist/bridge/messages/getUser.d.ts.map +1 -0
  83. package/dist/bridge/messages/getUser.js +32 -0
  84. package/dist/bridge/messages/hostToSandbox.d.ts +1089 -0
  85. package/dist/bridge/messages/hostToSandbox.d.ts.map +1 -0
  86. package/dist/bridge/messages/hostToSandbox.js +32 -0
  87. package/dist/bridge/messages/init.d.ts +209 -0
  88. package/dist/bridge/messages/init.d.ts.map +1 -0
  89. package/dist/bridge/messages/init.js +47 -0
  90. package/dist/bridge/messages/invalidHostMessage.d.ts +15 -0
  91. package/dist/bridge/messages/invalidHostMessage.d.ts.map +1 -0
  92. package/dist/bridge/messages/invalidHostMessage.js +13 -0
  93. package/dist/bridge/messages/invalidSandboxMessage.d.ts +15 -0
  94. package/dist/bridge/messages/invalidSandboxMessage.d.ts.map +1 -0
  95. package/dist/bridge/messages/invalidSandboxMessage.js +13 -0
  96. package/dist/bridge/messages/listUsers.d.ts +53 -0
  97. package/dist/bridge/messages/listUsers.d.ts.map +1 -0
  98. package/dist/bridge/messages/listUsers.js +33 -0
  99. package/dist/bridge/messages/pageChanged.d.ts +12 -0
  100. package/dist/bridge/messages/pageChanged.d.ts.map +1 -0
  101. package/dist/bridge/messages/pageChanged.js +9 -0
  102. package/dist/bridge/messages/parentChanged.d.ts +22 -0
  103. package/dist/bridge/messages/parentChanged.d.ts.map +1 -0
  104. package/dist/bridge/messages/parentChanged.js +9 -0
  105. package/dist/bridge/messages/queryDataSource.d.ts +20 -0
  106. package/dist/bridge/messages/queryDataSource.d.ts.map +1 -0
  107. package/dist/bridge/messages/queryDataSource.js +19 -0
  108. package/dist/bridge/messages/queryDataSourceResult.d.ts +90 -0
  109. package/dist/bridge/messages/queryDataSourceResult.d.ts.map +1 -0
  110. package/dist/bridge/messages/queryDataSourceResult.js +21 -0
  111. package/dist/bridge/messages/ready.d.ts +45 -0
  112. package/dist/bridge/messages/ready.d.ts.map +1 -0
  113. package/dist/bridge/messages/ready.js +37 -0
  114. package/dist/bridge/messages/resize.d.ts +12 -0
  115. package/dist/bridge/messages/resize.d.ts.map +1 -0
  116. package/dist/bridge/messages/resize.js +10 -0
  117. package/dist/bridge/messages/sandboxToHost.d.ts +410 -0
  118. package/dist/bridge/messages/sandboxToHost.d.ts.map +1 -0
  119. package/dist/bridge/messages/sandboxToHost.js +25 -0
  120. package/dist/bridge/messages/themeChanged.d.ts +11 -0
  121. package/dist/bridge/messages/themeChanged.d.ts.map +1 -0
  122. package/dist/bridge/messages/themeChanged.js +10 -0
  123. package/dist/bridge/messages/updatePage.d.ts +171 -0
  124. package/dist/bridge/messages/updatePage.d.ts.map +1 -0
  125. package/dist/bridge/messages/updatePage.js +15 -0
  126. package/dist/bridge/messages/updatePageResult.d.ts +210 -0
  127. package/dist/bridge/messages/updatePageResult.d.ts.map +1 -0
  128. package/dist/bridge/messages/updatePageResult.js +27 -0
  129. package/dist/bridge/pages/page.d.ts +600 -0
  130. package/dist/bridge/pages/page.d.ts.map +1 -0
  131. package/dist/bridge/pages/page.js +217 -0
  132. package/dist/bridge/parent.d.ts +25 -0
  133. package/dist/bridge/parent.d.ts.map +1 -0
  134. package/dist/bridge/parent.js +11 -0
  135. package/dist/bridge/pendingRequests.d.ts +14 -0
  136. package/dist/bridge/pendingRequests.d.ts.map +1 -0
  137. package/dist/bridge/pendingRequests.js +27 -0
  138. package/dist/bridge/sandboxClient.d.ts +63 -0
  139. package/dist/bridge/sandboxClient.d.ts.map +1 -0
  140. package/dist/bridge/sandboxClient.js +92 -0
  141. package/dist/bridge/theme.d.ts +4 -0
  142. package/dist/bridge/theme.d.ts.map +1 -0
  143. package/dist/bridge/theme.js +2 -0
  144. package/dist/bridge/users/user.d.ts +36 -0
  145. package/dist/bridge/users/user.d.ts.map +1 -0
  146. package/dist/bridge/users/user.js +19 -0
  147. package/dist/customBlock.d.ts +36 -0
  148. package/dist/customBlock.d.ts.map +1 -0
  149. package/dist/customBlock.js +65 -0
  150. package/dist/host/createCustomBlockHost.d.ts +34 -0
  151. package/dist/host/createCustomBlockHost.d.ts.map +1 -0
  152. package/dist/host/createCustomBlockHost.js +278 -0
  153. package/dist/host/lifecycle/initErrors.d.ts +10 -0
  154. package/dist/host/lifecycle/initErrors.d.ts.map +1 -0
  155. package/dist/host/lifecycle/initErrors.js +123 -0
  156. package/dist/host/lifecycle/ready.d.ts +8 -0
  157. package/dist/host/lifecycle/ready.d.ts.map +1 -0
  158. package/dist/host/lifecycle/ready.js +24 -0
  159. package/dist/host/lifecycle/types.d.ts +24 -0
  160. package/dist/host/lifecycle/types.d.ts.map +1 -0
  161. package/dist/host/lifecycle/types.js +1 -0
  162. package/dist/host/messages/invalidSandboxMessage.d.ts +7 -0
  163. package/dist/host/messages/invalidSandboxMessage.d.ts.map +1 -0
  164. package/dist/host/messages/invalidSandboxMessage.js +24 -0
  165. package/dist/host/messages/types.d.ts +60 -0
  166. package/dist/host/messages/types.d.ts.map +1 -0
  167. package/dist/host/messages/types.js +1 -0
  168. package/dist/host/queries/querySubscriptions.d.ts +20 -0
  169. package/dist/host/queries/querySubscriptions.d.ts.map +1 -0
  170. package/dist/host/queries/querySubscriptions.js +29 -0
  171. package/dist/host/queries/types.d.ts +9 -0
  172. package/dist/host/queries/types.d.ts.map +1 -0
  173. package/dist/host/queries/types.js +1 -0
  174. package/dist/host.d.ts +73 -0
  175. package/dist/host.d.ts.map +1 -0
  176. package/dist/host.js +42 -0
  177. package/dist/index.d.ts +37 -0
  178. package/dist/index.d.ts.map +1 -0
  179. package/dist/index.js +14 -0
  180. package/dist/init.d.ts +53 -0
  181. package/dist/init.d.ts.map +1 -0
  182. package/dist/init.js +87 -0
  183. package/dist/react/DebugMessageLog.d.ts +2 -0
  184. package/dist/react/DebugMessageLog.d.ts.map +1 -0
  185. package/dist/react/DebugMessageLog.js +22 -0
  186. package/dist/react/NotionCustomBlock.css +110 -0
  187. package/dist/react/NotionCustomBlock.d.ts +50 -0
  188. package/dist/react/NotionCustomBlock.d.ts.map +1 -0
  189. package/dist/react/NotionCustomBlock.js +81 -0
  190. package/dist/react/index.d.ts +14 -0
  191. package/dist/react/index.d.ts.map +1 -0
  192. package/dist/react/index.js +13 -0
  193. package/dist/react/standalonePreview.d.ts +2 -0
  194. package/dist/react/standalonePreview.d.ts.map +1 -0
  195. package/dist/react/standalonePreview.js +26 -0
  196. package/dist/react/useCustomBlockAutoResize.d.ts +30 -0
  197. package/dist/react/useCustomBlockAutoResize.d.ts.map +1 -0
  198. package/dist/react/useCustomBlockAutoResize.js +35 -0
  199. package/dist/react/useCustomBlockInit.d.ts +43 -0
  200. package/dist/react/useCustomBlockInit.d.ts.map +1 -0
  201. package/dist/react/useCustomBlockInit.js +60 -0
  202. package/dist/react/useDataSource.d.ts +13 -0
  203. package/dist/react/useDataSource.d.ts.map +1 -0
  204. package/dist/react/useDataSource.js +37 -0
  205. package/dist/react/useHostState.d.ts +2 -0
  206. package/dist/react/useHostState.d.ts.map +1 -0
  207. package/dist/react/useHostState.js +5 -0
  208. package/dist/react/useRuntimeState.d.ts +66 -0
  209. package/dist/react/useRuntimeState.d.ts.map +1 -0
  210. package/dist/react/useRuntimeState.js +73 -0
  211. package/dist/types.d.ts +154 -0
  212. package/dist/types.d.ts.map +1 -0
  213. package/dist/types.js +1 -0
  214. package/dist/utils.d.ts +9 -0
  215. package/dist/utils.d.ts.map +1 -0
  216. package/dist/utils.js +10 -0
  217. package/dist/version.d.ts +9 -0
  218. package/dist/version.d.ts.map +1 -0
  219. package/dist/version.js +7 -0
  220. package/docs/block-location.md +83 -0
  221. package/docs/data-sources.md +186 -0
  222. package/docs/lifecycle.md +172 -0
  223. package/docs/manifest.md +42 -0
  224. package/docs/pages.md +143 -0
  225. package/docs/users.md +92 -0
  226. package/package.json +69 -0
  227. package/src/autoResize.ts +84 -0
  228. package/src/bridge/SandboxBridge.ts +921 -0
  229. package/src/bridge/dataSources/dataSource.ts +63 -0
  230. package/src/bridge/dataSources/dataSourcePage.ts +71 -0
  231. package/src/bridge/dataSources/dataSourceValue.ts +19 -0
  232. package/src/bridge/dataSources/dateValue.ts +96 -0
  233. package/src/bridge/dataSources/errors.ts +14 -0
  234. package/src/bridge/dataSources/propertySchema.ts +186 -0
  235. package/src/bridge/dataSources/recordPointer.ts +13 -0
  236. package/src/bridge/dataSources/resolve.ts +99 -0
  237. package/src/bridge/dataSources/resolveProperty.ts +130 -0
  238. package/src/bridge/errors.ts +13 -0
  239. package/src/bridge/hostState.ts +154 -0
  240. package/src/bridge/ids.ts +58 -0
  241. package/src/bridge/incomingType.ts +19 -0
  242. package/src/bridge/loadManifest.ts +89 -0
  243. package/src/bridge/manifest.ts +53 -0
  244. package/src/bridge/messages/createPage.ts +67 -0
  245. package/src/bridge/messages/createPageResult.ts +52 -0
  246. package/src/bridge/messages/currentUserChanged.ts +14 -0
  247. package/src/bridge/messages/dataSourcesChanged.ts +18 -0
  248. package/src/bridge/messages/getPage.ts +52 -0
  249. package/src/bridge/messages/getUser.ts +48 -0
  250. package/src/bridge/messages/hostToSandbox.ts +37 -0
  251. package/src/bridge/messages/init.ts +81 -0
  252. package/src/bridge/messages/invalidHostMessage.ts +16 -0
  253. package/src/bridge/messages/invalidSandboxMessage.ts +18 -0
  254. package/src/bridge/messages/listUsers.ts +49 -0
  255. package/src/bridge/messages/pageChanged.ts +12 -0
  256. package/src/bridge/messages/parentChanged.ts +14 -0
  257. package/src/bridge/messages/queryDataSource.ts +24 -0
  258. package/src/bridge/messages/queryDataSourceResult.ts +38 -0
  259. package/src/bridge/messages/ready.ts +41 -0
  260. package/src/bridge/messages/resize.ts +13 -0
  261. package/src/bridge/messages/sandboxToHost.ts +30 -0
  262. package/src/bridge/messages/themeChanged.ts +15 -0
  263. package/src/bridge/messages/updatePage.ts +22 -0
  264. package/src/bridge/messages/updatePageResult.ts +49 -0
  265. package/src/bridge/pages/page.ts +281 -0
  266. package/src/bridge/parent.ts +27 -0
  267. package/src/bridge/pendingRequests.ts +28 -0
  268. package/src/bridge/sandboxClient.ts +137 -0
  269. package/src/bridge/theme.ts +5 -0
  270. package/src/bridge/users/user.ts +31 -0
  271. package/src/css.d.ts +1 -0
  272. package/src/customBlock.ts +102 -0
  273. package/src/host/createCustomBlockHost.ts +392 -0
  274. package/src/host/lifecycle/initErrors.ts +132 -0
  275. package/src/host/lifecycle/ready.ts +36 -0
  276. package/src/host/lifecycle/types.ts +28 -0
  277. package/src/host/messages/invalidSandboxMessage.ts +38 -0
  278. package/src/host/messages/types.ts +67 -0
  279. package/src/host/queries/querySubscriptions.ts +52 -0
  280. package/src/host/queries/types.ts +16 -0
  281. package/src/host.ts +167 -0
  282. package/src/index.ts +115 -0
  283. package/src/init.ts +143 -0
  284. package/src/react/DebugMessageLog.tsx +30 -0
  285. package/src/react/NotionCustomBlock.css +110 -0
  286. package/src/react/NotionCustomBlock.tsx +151 -0
  287. package/src/react/index.ts +28 -0
  288. package/src/react/standalonePreview.ts +28 -0
  289. package/src/react/useCustomBlockAutoResize.ts +46 -0
  290. package/src/react/useCustomBlockInit.ts +91 -0
  291. package/src/react/useDataSource.ts +47 -0
  292. package/src/react/useHostState.ts +9 -0
  293. package/src/react/useRuntimeState.ts +85 -0
  294. package/src/types.ts +175 -0
  295. package/src/utils.ts +13 -0
  296. package/src/version.ts +8 -0
  297. package/vite-plugin/index.d.ts +46 -0
  298. package/vite-plugin/index.js +115 -0
@@ -0,0 +1,281 @@
1
+ /**
2
+ * Notion page shapes exchanged over the custom block bridge.
3
+ *
4
+ * These mirror a narrow subset of Notion's public `POST /v1/pages` API, since that's the bridge
5
+ * shape the host delivers for messages like `createPageResult`.
6
+ */
7
+
8
+ import * as v from "valibot"
9
+ import { notionDataSourceIdSchema, notionPageIdSchema } from "../ids.js"
10
+ import { notionParentSchema } from "../parent.js"
11
+
12
+ export type { NotionPageId } from "../ids.js"
13
+
14
+ export const customBlockPageSchema = v.object({
15
+ id: notionPageIdSchema,
16
+ })
17
+
18
+ export type CustomBlockPage = v.InferOutput<typeof customBlockPageSchema>
19
+
20
+ /**
21
+ * Parent reference accepted by `pages.create` / `pages.update` inputs.
22
+ *
23
+ * Mirrors the parent shape Notion's public `POST /v1/pages` API accepts: `page_id` for a
24
+ * page-parented child, `data_source_id` for a database row. `data_source_id` is the internal
25
+ * collection ID.
26
+ */
27
+ export const notionPageParentInputSchema = v.variant("type", [
28
+ v.object({ type: v.literal("page_id"), page_id: notionPageIdSchema }),
29
+ v.object({
30
+ type: v.literal("data_source_id"),
31
+ data_source_id: notionDataSourceIdSchema,
32
+ }),
33
+ ])
34
+ export type NotionPageParentInput = v.InferOutput<
35
+ typeof notionPageParentInputSchema
36
+ >
37
+
38
+ export const notionEmojiIconSchema = v.object({
39
+ type: v.literal("emoji"),
40
+ emoji: v.string(),
41
+ })
42
+ export const notionCustomEmojiIconSchema = v.object({
43
+ type: v.literal("custom_emoji"),
44
+ custom_emoji: v.object({
45
+ id: v.string(),
46
+ name: v.optional(v.string()),
47
+ url: v.optional(v.string()),
48
+ }),
49
+ })
50
+ export const notionExternalFileSchema = v.object({
51
+ type: v.literal("external"),
52
+ external: v.object({ url: v.string() }),
53
+ })
54
+ export const notionHostedFileSchema = v.object({
55
+ type: v.literal("file"),
56
+ file: v.object({
57
+ url: v.string(),
58
+ expiry_time: v.optional(v.string()),
59
+ }),
60
+ })
61
+
62
+ // TODO(custom-blocks): Add file upload support.
63
+ export const notionPageIconSchema = v.variant("type", [
64
+ notionEmojiIconSchema,
65
+ notionCustomEmojiIconSchema,
66
+ notionExternalFileSchema,
67
+ notionHostedFileSchema,
68
+ ])
69
+ export type NotionPageIcon = v.InferOutput<typeof notionPageIconSchema>
70
+
71
+ export const notionPageCoverSchema = v.variant("type", [
72
+ notionExternalFileSchema,
73
+ notionHostedFileSchema,
74
+ ])
75
+ export type NotionPageCover = v.InferOutput<typeof notionPageCoverSchema>
76
+
77
+ const nullableStringSchema = v.nullable(v.string())
78
+
79
+ const notionRichTextItemSchema = v.record(v.string(), v.unknown())
80
+ export type NotionRichTextItem = v.InferOutput<typeof notionRichTextItemSchema>
81
+
82
+ const notionSelectOptionInputSchema = v.union([
83
+ v.object({
84
+ id: v.string(),
85
+ name: v.optional(v.string()),
86
+ color: v.optional(v.string()),
87
+ description: v.optional(nullableStringSchema),
88
+ }),
89
+ v.object({
90
+ name: v.string(),
91
+ id: v.optional(v.string()),
92
+ color: v.optional(v.string()),
93
+ description: v.optional(nullableStringSchema),
94
+ }),
95
+ ])
96
+ export type NotionSelectOptionInput = v.InferOutput<
97
+ typeof notionSelectOptionInputSchema
98
+ >
99
+
100
+ const notionDateInputSchema = v.object({
101
+ start: v.string(),
102
+ end: v.optional(nullableStringSchema),
103
+ time_zone: v.optional(nullableStringSchema),
104
+ })
105
+ export type NotionDateInput = v.InferOutput<typeof notionDateInputSchema>
106
+
107
+ const notionUserInputSchema = v.union([
108
+ v.object({
109
+ object: v.optional(v.literal("user")),
110
+ id: v.string(),
111
+ }),
112
+ v.object({
113
+ object: v.literal("group"),
114
+ id: v.string(),
115
+ name: v.optional(nullableStringSchema),
116
+ }),
117
+ ])
118
+ export type NotionUserInput = v.InferOutput<typeof notionUserInputSchema>
119
+
120
+ const notionRelationInputSchema = v.object({ id: v.string() })
121
+ export type NotionRelationInput = v.InferOutput<
122
+ typeof notionRelationInputSchema
123
+ >
124
+
125
+ const notionFileInputSchema = v.union([
126
+ v.object({
127
+ type: v.literal("external"),
128
+ name: v.string(),
129
+ external: v.object({ url: v.string() }),
130
+ }),
131
+ v.object({
132
+ type: v.literal("file"),
133
+ name: v.string(),
134
+ file: v.object({
135
+ url: v.string(),
136
+ expiry_time: v.optional(v.string()),
137
+ }),
138
+ }),
139
+ ])
140
+ export type NotionFileInput = v.InferOutput<typeof notionFileInputSchema>
141
+
142
+ const notionPlaceInputSchema = v.object({
143
+ lat: v.number(),
144
+ lon: v.number(),
145
+ name: v.optional(nullableStringSchema),
146
+ address: v.optional(nullableStringSchema),
147
+ aws_place_id: v.optional(nullableStringSchema),
148
+ google_place_id: v.optional(nullableStringSchema),
149
+ })
150
+ export type NotionPlaceInput = v.InferOutput<typeof notionPlaceInputSchema>
151
+
152
+ const pagePropertyBaseSchema = {
153
+ id: v.string(),
154
+ }
155
+
156
+ /**
157
+ * A page property value.
158
+ */
159
+ export const notionPagePropertyValueSchema = v.variant("type", [
160
+ v.object({
161
+ ...pagePropertyBaseSchema,
162
+ type: v.literal("title"),
163
+ title: v.array(notionRichTextItemSchema),
164
+ }),
165
+ v.object({
166
+ ...pagePropertyBaseSchema,
167
+ type: v.literal("rich_text"),
168
+ rich_text: v.array(notionRichTextItemSchema),
169
+ }),
170
+ v.object({
171
+ ...pagePropertyBaseSchema,
172
+ type: v.literal("number"),
173
+ number: v.nullable(v.number()),
174
+ }),
175
+ v.object({
176
+ ...pagePropertyBaseSchema,
177
+ type: v.literal("url"),
178
+ url: nullableStringSchema,
179
+ }),
180
+ v.object({
181
+ ...pagePropertyBaseSchema,
182
+ type: v.literal("email"),
183
+ email: nullableStringSchema,
184
+ }),
185
+ v.object({
186
+ ...pagePropertyBaseSchema,
187
+ type: v.literal("phone_number"),
188
+ phone_number: nullableStringSchema,
189
+ }),
190
+ v.object({
191
+ ...pagePropertyBaseSchema,
192
+ type: v.literal("checkbox"),
193
+ checkbox: v.boolean(),
194
+ }),
195
+ v.object({
196
+ ...pagePropertyBaseSchema,
197
+ type: v.literal("select"),
198
+ select: v.nullable(notionSelectOptionInputSchema),
199
+ }),
200
+ v.object({
201
+ ...pagePropertyBaseSchema,
202
+ type: v.literal("status"),
203
+ status: v.nullable(notionSelectOptionInputSchema),
204
+ }),
205
+ v.object({
206
+ ...pagePropertyBaseSchema,
207
+ type: v.literal("multi_select"),
208
+ multi_select: v.array(notionSelectOptionInputSchema),
209
+ }),
210
+ v.object({
211
+ ...pagePropertyBaseSchema,
212
+ type: v.literal("date"),
213
+ date: v.nullable(notionDateInputSchema),
214
+ }),
215
+ v.object({
216
+ ...pagePropertyBaseSchema,
217
+ type: v.literal("people"),
218
+ people: v.array(notionUserInputSchema),
219
+ }),
220
+ v.object({
221
+ ...pagePropertyBaseSchema,
222
+ type: v.literal("relation"),
223
+ has_more: v.optional(v.boolean()),
224
+ relation: v.array(notionRelationInputSchema),
225
+ }),
226
+ v.object({
227
+ ...pagePropertyBaseSchema,
228
+ type: v.literal("files"),
229
+ files: v.array(notionFileInputSchema),
230
+ }),
231
+ v.object({
232
+ ...pagePropertyBaseSchema,
233
+ type: v.literal("place"),
234
+ place: v.nullable(notionPlaceInputSchema),
235
+ }),
236
+ ])
237
+ export type NotionPagePropertyValue = v.InferOutput<
238
+ typeof notionPagePropertyValueSchema
239
+ >
240
+
241
+ type WithOptionalPropertyId<T> = T extends { id: string }
242
+ ? Omit<T, "id"> & { id?: string }
243
+ : never
244
+
245
+ /**
246
+ * Public SDK page property write input. Keys may be raw property IDs or data-source
247
+ * property keys. `id` is optional because the SDK resolves the final raw property ID
248
+ * from the map key before sending the bridge message.
249
+ */
250
+ export type NotionPagePropertyInputValue =
251
+ WithOptionalPropertyId<NotionPagePropertyValue>
252
+
253
+ export type NotionPagePropertyInputMap = {
254
+ [propertyIdOrKey: string]: NotionPagePropertyInputValue
255
+ }
256
+
257
+ export const notionPagePropertyWriteMapSchema = v.record(
258
+ v.string(),
259
+ notionPagePropertyValueSchema,
260
+ )
261
+ export type NotionPagePropertyWriteMap = v.InferOutput<
262
+ typeof notionPagePropertyWriteMapSchema
263
+ >
264
+
265
+ /**
266
+ * The `Page` object returned in `createPageResult` messages.
267
+ */
268
+ export const notionPageSchema = v.object({
269
+ object: v.literal("page"),
270
+ id: notionPageIdSchema,
271
+ parent: notionParentSchema,
272
+ properties: notionPagePropertyWriteMapSchema,
273
+ created_time: v.optional(v.string()),
274
+ last_edited_time: v.optional(v.string()),
275
+ icon: v.optional(notionPageIconSchema),
276
+ cover: v.optional(notionPageCoverSchema),
277
+ url: v.optional(v.string()),
278
+ public_url: v.optional(v.string()),
279
+ in_trash: v.optional(v.boolean()),
280
+ })
281
+ export type NotionPage = v.InferOutput<typeof notionPageSchema>
@@ -0,0 +1,27 @@
1
+ import * as v from "valibot"
2
+ import {
3
+ notionBlockIdSchema,
4
+ notionDataSourceIdSchema,
5
+ notionPageIdSchema,
6
+ } from "./ids.js"
7
+
8
+ export const notionParentSchema = v.variant("type", [
9
+ v.object({ type: v.literal("page_id"), page_id: notionPageIdSchema }),
10
+ v.object({
11
+ type: v.literal("data_source_id"),
12
+ data_source_id: notionDataSourceIdSchema,
13
+ }),
14
+ v.object({ type: v.literal("workspace"), workspace: v.literal(true) }),
15
+ v.object({ type: v.literal("block_id"), block_id: notionBlockIdSchema }),
16
+ ])
17
+
18
+ /**
19
+ * A record's parent reference.
20
+ *
21
+ * Mirrors Notion's public API:
22
+ * - `page_id` — parented directly under a page.
23
+ * - `block_id` — parented under a non-page container block (toggle, column, callout, ...).
24
+ * - `data_source_id` — parented under a collection (data source).
25
+ * - `workspace` — top-level / team-rooted.
26
+ */
27
+ export type NotionParent = v.InferOutput<typeof notionParentSchema>
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Tracks one-shot request/response pairs over the `postMessage` bridge. Each `allocate` reserves a
3
+ * unique `requestId` and stores its resolver. `resolve` finds the pending resolver by `requestId`
4
+ * and calls it, then removes the entry so the same `requestId` cannot be resolved twice.
5
+ */
6
+ export class PendingRequests<T> {
7
+ private nextId = 1
8
+ private readonly entries = new Map<string, (value: T) => void>()
9
+
10
+ constructor(private readonly prefix: string) {}
11
+
12
+ allocate(resolver: (value: T) => void): string {
13
+ const requestId = `${this.prefix}-${this.nextId}`
14
+ this.nextId += 1
15
+ this.entries.set(requestId, resolver)
16
+ return requestId
17
+ }
18
+
19
+ resolve(requestId: string, value: T): boolean {
20
+ const resolver = this.entries.get(requestId)
21
+ if (resolver === undefined) {
22
+ return false
23
+ }
24
+ this.entries.delete(requestId)
25
+ resolver(value)
26
+ return true
27
+ }
28
+ }
@@ -0,0 +1,137 @@
1
+ import type {
2
+ CreatePageInput,
3
+ CreatePageResult,
4
+ GetPageResult,
5
+ GetUserResult,
6
+ ListUsersInput,
7
+ ListUsersResult,
8
+ NotionPageId,
9
+ NotionUserId,
10
+ UpdatePageInput,
11
+ UpdatePageResult,
12
+ UseDataSourceOptions,
13
+ } from "../types.js"
14
+ import {
15
+ type CustomBlockHostState,
16
+ type DataSourceQueryView,
17
+ getDataSourceQueryView as getDataSourceQueryViewWithBridge,
18
+ } from "./hostState.js"
19
+ import type { ManifestLoadResult } from "./loadManifest.js"
20
+ import type { CustomBlockManifest } from "./manifest.js"
21
+ import type { InitMessage } from "./messages/init.js"
22
+ import { type MessageLogEntry, SandboxBridge } from "./SandboxBridge.js"
23
+
24
+ export type { MessageLogEntry }
25
+
26
+ const bridge = new SandboxBridge()
27
+
28
+ export const customBlockHost = {
29
+ sendReady: (manifestResult: ManifestLoadResult) => {
30
+ bridge.sendReady(manifestResult)
31
+ },
32
+
33
+ awaitInit: (signal?: AbortSignal): Promise<InitMessage> => {
34
+ return bridge.awaitInit(signal)
35
+ },
36
+
37
+ subscribe: (listener: () => void) => {
38
+ return bridge.subscribe(listener)
39
+ },
40
+
41
+ getState: (): CustomBlockHostState => {
42
+ return bridge.getHostState()
43
+ },
44
+
45
+ getManifest: (): CustomBlockManifest | null => {
46
+ return bridge.getManifest()
47
+ },
48
+
49
+ /**
50
+ * Apply an `init` payload directly, bypassing the postMessage handshake for
51
+ * standalone preview state.
52
+ */
53
+ setMockState: (message: InitMessage) => {
54
+ bridge.setMockState(message)
55
+ },
56
+
57
+ postResize: (height: number) => {
58
+ bridge.postResize(height)
59
+ },
60
+ }
61
+
62
+ export const customBlockDataSources = {
63
+ query: (key: string, options?: UseDataSourceOptions) => {
64
+ bridge.queryDataSource(key, options)
65
+ },
66
+
67
+ getView: (
68
+ hostState: CustomBlockHostState,
69
+ key: string,
70
+ ): DataSourceQueryView => {
71
+ return getDataSourceQueryViewWithBridge(hostState, key, args =>
72
+ bridge.updateDataSourcePage(args),
73
+ )
74
+ },
75
+ }
76
+
77
+ export const messageLog = {
78
+ getSnapshot: (): readonly MessageLogEntry[] => {
79
+ return bridge.getMessageLog()
80
+ },
81
+
82
+ subscribe: (listener: () => void) => {
83
+ return bridge.subscribeToMessageLog(listener)
84
+ },
85
+ }
86
+
87
+ /**
88
+ * Page-related SDK APIs exposed under `sdk.pages.*`.
89
+ */
90
+ export const pages = {
91
+ /**
92
+ * Creates a new Notion page.
93
+ */
94
+ create: (input: CreatePageInput): Promise<CreatePageResult> => {
95
+ return bridge.createPage(input)
96
+ },
97
+
98
+ /**
99
+ * Fetches a page by id.
100
+ */
101
+ get: (pageId: NotionPageId): Promise<GetPageResult> => {
102
+ return bridge.getPage(pageId)
103
+ },
104
+
105
+ /**
106
+ * Updates an existing page.
107
+ */
108
+ update: (input: UpdatePageInput): Promise<UpdatePageResult> => {
109
+ return bridge.updatePage(input)
110
+ },
111
+
112
+ /**
113
+ * Soft-delete a page by archiving it.
114
+ */
115
+ delete: (pageId: NotionPageId): Promise<UpdatePageResult> => {
116
+ return bridge.updatePage({ pageId, archived: true })
117
+ },
118
+ }
119
+
120
+ /**
121
+ * User-related SDK APIs exposed under `sdk.users.*`.
122
+ */
123
+ export const users = {
124
+ /**
125
+ * Lists users visible in the current custom block workspace.
126
+ */
127
+ list: (input?: ListUsersInput): Promise<ListUsersResult> => {
128
+ return bridge.listUsers(input)
129
+ },
130
+
131
+ /**
132
+ * Fetches a user by id.
133
+ */
134
+ get: (userId: NotionUserId): Promise<GetUserResult> => {
135
+ return bridge.getUser(userId)
136
+ },
137
+ }
@@ -0,0 +1,5 @@
1
+ import * as v from "valibot"
2
+
3
+ export const notionThemeSchema = v.picklist(["light", "dark"])
4
+
5
+ export type NotionTheme = v.InferOutput<typeof notionThemeSchema>
@@ -0,0 +1,31 @@
1
+ import * as v from "valibot"
2
+
3
+ declare const notionUserIdBrand: unique symbol
4
+
5
+ export type NotionUserId = string & {
6
+ readonly [notionUserIdBrand]: "NotionUserId"
7
+ }
8
+
9
+ export const notionUserSchema = v.object({
10
+ object: v.literal("user"),
11
+ id: v.string(),
12
+ name: v.optional(v.string()),
13
+ avatar_url: v.nullable(v.string()),
14
+ type: v.literal("person"),
15
+ person: v.object({
16
+ email: v.string(),
17
+ }),
18
+ })
19
+
20
+ export type NotionUser = v.InferOutput<typeof notionUserSchema>
21
+
22
+ export const notionUserListSchema = v.object({
23
+ object: v.literal("list"),
24
+ results: v.array(notionUserSchema),
25
+ next_cursor: v.nullable(v.string()),
26
+ has_more: v.boolean(),
27
+ type: v.literal("user"),
28
+ user: v.record(v.string(), v.unknown()),
29
+ })
30
+
31
+ export type NotionUserList = v.InferOutput<typeof notionUserListSchema>
package/src/css.d.ts ADDED
@@ -0,0 +1 @@
1
+ declare module "*.css"
@@ -0,0 +1,102 @@
1
+ import { autoResize } from "./autoResize.js"
2
+ import type { NotionDataSource } from "./bridge/dataSources/dataSource.js"
3
+ import type {
4
+ CustomBlockHostState,
5
+ InitializedHostState,
6
+ } from "./bridge/hostState.js"
7
+ import type { NotionBlockId } from "./bridge/ids.js"
8
+ import type { CustomBlockManifest } from "./bridge/manifest.js"
9
+ import type { CustomBlockPage } from "./bridge/pages/page.js"
10
+ import type { NotionParent } from "./bridge/parent.js"
11
+ import { customBlockHost } from "./bridge/sandboxClient.js"
12
+ import type { NotionTheme } from "./bridge/theme.js"
13
+ import type { NotionUser } from "./bridge/users/user.js"
14
+
15
+ export type CustomBlockState =
16
+ | { status: "uninitialized"; theme: NotionTheme }
17
+ | {
18
+ status: "initialized"
19
+ theme: NotionTheme
20
+ blockId: NotionBlockId
21
+ parent: NotionParent
22
+ page: CustomBlockPage
23
+ currentUser: NotionUser
24
+ dataSources: NotionDataSource[]
25
+ }
26
+
27
+ /**
28
+ * Framework-neutral runtime state APIs for a custom block. Call `initCustomBlock`
29
+ * before reading initialized values, and use `subscribe` to react to host pushes.
30
+ */
31
+ export const customBlock = {
32
+ subscribe(listener: () => void): () => void {
33
+ return customBlockHost.subscribe(listener)
34
+ },
35
+
36
+ getState(): CustomBlockState {
37
+ return toPublicState(customBlockHost.getState())
38
+ },
39
+
40
+ getCurrentUser(): NotionUser {
41
+ return getInitializedHostState("getCurrentUser").currentUser
42
+ },
43
+
44
+ getTheme(): NotionTheme {
45
+ return getInitializedHostState("getTheme").theme
46
+ },
47
+
48
+ getBlockId(): NotionBlockId {
49
+ return getInitializedHostState("getBlockId").blockId
50
+ },
51
+
52
+ getParent(): NotionParent {
53
+ return getInitializedHostState("getParent").parent
54
+ },
55
+
56
+ getPage(): CustomBlockPage {
57
+ return getInitializedHostState("getPage").page
58
+ },
59
+
60
+ getManifest(): CustomBlockManifest | null {
61
+ return customBlockHost.getManifest()
62
+ },
63
+
64
+ autoResize,
65
+ }
66
+
67
+ let lastHostState: CustomBlockHostState | undefined
68
+ let lastPublicState: CustomBlockState | undefined
69
+
70
+ function toPublicState(hostState: CustomBlockHostState): CustomBlockState {
71
+ if (hostState === lastHostState && lastPublicState !== undefined) {
72
+ return lastPublicState
73
+ }
74
+ lastHostState = hostState
75
+ if (hostState.status === "uninitialized") {
76
+ lastPublicState = {
77
+ status: "uninitialized",
78
+ theme: hostState.theme,
79
+ }
80
+ return lastPublicState
81
+ }
82
+ lastPublicState = {
83
+ status: "initialized",
84
+ theme: hostState.theme,
85
+ blockId: hostState.blockId,
86
+ parent: hostState.parent,
87
+ page: hostState.page,
88
+ currentUser: hostState.currentUser,
89
+ dataSources: hostState.dataSources,
90
+ }
91
+ return lastPublicState
92
+ }
93
+
94
+ function getInitializedHostState(methodName: string): InitializedHostState {
95
+ const hostState = customBlockHost.getState()
96
+ if (hostState.status !== "initialized") {
97
+ throw new Error(
98
+ `customBlock.${methodName} called before \`initCustomBlock\` resolved. Await it before reading runtime state.`,
99
+ )
100
+ }
101
+ return hostState
102
+ }