@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.
- package/HOST.md +171 -0
- package/README.md +57 -0
- package/bin/cli/attach.js +180 -0
- package/bin/cli/cli.js +248 -0
- package/bin/cli/create.js +106 -0
- package/bin/cli/datasources.js +255 -0
- package/bin/cli/deploy.js +109 -0
- package/bin/cli/ids.js +13 -0
- package/bin/cli/ntn.js +95 -0
- package/bin/cli/pullData.js +76 -0
- package/bin/cli/pullManifest.js +158 -0
- package/bin/cli/target.js +95 -0
- package/bin/src/bridge/dataSources/propertySchema.js +148 -0
- package/bin/src/bridge/manifest.js +40 -0
- package/dist/autoResize.d.ts +4 -0
- package/dist/autoResize.d.ts.map +1 -0
- package/dist/autoResize.js +71 -0
- package/dist/bridge/SandboxBridge.d.ts +92 -0
- package/dist/bridge/SandboxBridge.d.ts.map +1 -0
- package/dist/bridge/SandboxBridge.js +718 -0
- package/dist/bridge/dataSources/dataSource.d.ts +732 -0
- package/dist/bridge/dataSources/dataSource.d.ts.map +1 -0
- package/dist/bridge/dataSources/dataSource.js +37 -0
- package/dist/bridge/dataSources/dataSourcePage.d.ts +118 -0
- package/dist/bridge/dataSources/dataSourcePage.d.ts.map +1 -0
- package/dist/bridge/dataSources/dataSourcePage.js +14 -0
- package/dist/bridge/dataSources/dataSourceValue.d.ts +67 -0
- package/dist/bridge/dataSources/dataSourceValue.d.ts.map +1 -0
- package/dist/bridge/dataSources/dataSourceValue.js +14 -0
- package/dist/bridge/dataSources/dateValue.d.ts +158 -0
- package/dist/bridge/dataSources/dateValue.d.ts.map +1 -0
- package/dist/bridge/dataSources/dateValue.js +59 -0
- package/dist/bridge/dataSources/errors.d.ts +6 -0
- package/dist/bridge/dataSources/errors.d.ts.map +1 -0
- package/dist/bridge/dataSources/errors.js +4 -0
- package/dist/bridge/dataSources/propertySchema.d.ts +191 -0
- package/dist/bridge/dataSources/propertySchema.d.ts.map +1 -0
- package/dist/bridge/dataSources/propertySchema.js +148 -0
- package/dist/bridge/dataSources/recordPointer.d.ts +10 -0
- package/dist/bridge/dataSources/recordPointer.d.ts.map +1 -0
- package/dist/bridge/dataSources/recordPointer.js +8 -0
- package/dist/bridge/dataSources/resolve.d.ts +22 -0
- package/dist/bridge/dataSources/resolve.d.ts.map +1 -0
- package/dist/bridge/dataSources/resolve.js +65 -0
- package/dist/bridge/dataSources/resolveProperty.d.ts +41 -0
- package/dist/bridge/dataSources/resolveProperty.d.ts.map +1 -0
- package/dist/bridge/dataSources/resolveProperty.js +73 -0
- package/dist/bridge/errors.d.ts +12 -0
- package/dist/bridge/errors.d.ts.map +1 -0
- package/dist/bridge/errors.js +6 -0
- package/dist/bridge/hostState.d.ts +65 -0
- package/dist/bridge/hostState.d.ts.map +1 -0
- package/dist/bridge/hostState.js +65 -0
- package/dist/bridge/ids.d.ts +39 -0
- package/dist/bridge/ids.d.ts.map +1 -0
- package/dist/bridge/ids.js +5 -0
- package/dist/bridge/incomingType.d.ts +10 -0
- package/dist/bridge/incomingType.d.ts.map +1 -0
- package/dist/bridge/incomingType.js +17 -0
- package/dist/bridge/loadManifest.d.ts +25 -0
- package/dist/bridge/loadManifest.d.ts.map +1 -0
- package/dist/bridge/loadManifest.js +68 -0
- package/dist/bridge/manifest.d.ts +66 -0
- package/dist/bridge/manifest.d.ts.map +1 -0
- package/dist/bridge/manifest.js +40 -0
- package/dist/bridge/messages/createPage.d.ts +225 -0
- package/dist/bridge/messages/createPage.d.ts.map +1 -0
- package/dist/bridge/messages/createPage.js +46 -0
- package/dist/bridge/messages/createPageResult.d.ts +211 -0
- package/dist/bridge/messages/createPageResult.d.ts.map +1 -0
- package/dist/bridge/messages/createPageResult.js +28 -0
- package/dist/bridge/messages/currentUserChanged.d.ts +19 -0
- package/dist/bridge/messages/currentUserChanged.d.ts.map +1 -0
- package/dist/bridge/messages/currentUserChanged.js +9 -0
- package/dist/bridge/messages/dataSourcesChanged.d.ts +158 -0
- package/dist/bridge/messages/dataSourcesChanged.d.ts.map +1 -0
- package/dist/bridge/messages/dataSourcesChanged.js +13 -0
- package/dist/bridge/messages/getPage.d.ts +216 -0
- package/dist/bridge/messages/getPage.d.ts.map +1 -0
- package/dist/bridge/messages/getPage.js +33 -0
- package/dist/bridge/messages/getUser.d.ts +45 -0
- package/dist/bridge/messages/getUser.d.ts.map +1 -0
- package/dist/bridge/messages/getUser.js +32 -0
- package/dist/bridge/messages/hostToSandbox.d.ts +1089 -0
- package/dist/bridge/messages/hostToSandbox.d.ts.map +1 -0
- package/dist/bridge/messages/hostToSandbox.js +32 -0
- package/dist/bridge/messages/init.d.ts +209 -0
- package/dist/bridge/messages/init.d.ts.map +1 -0
- package/dist/bridge/messages/init.js +47 -0
- package/dist/bridge/messages/invalidHostMessage.d.ts +15 -0
- package/dist/bridge/messages/invalidHostMessage.d.ts.map +1 -0
- package/dist/bridge/messages/invalidHostMessage.js +13 -0
- package/dist/bridge/messages/invalidSandboxMessage.d.ts +15 -0
- package/dist/bridge/messages/invalidSandboxMessage.d.ts.map +1 -0
- package/dist/bridge/messages/invalidSandboxMessage.js +13 -0
- package/dist/bridge/messages/listUsers.d.ts +53 -0
- package/dist/bridge/messages/listUsers.d.ts.map +1 -0
- package/dist/bridge/messages/listUsers.js +33 -0
- package/dist/bridge/messages/pageChanged.d.ts +12 -0
- package/dist/bridge/messages/pageChanged.d.ts.map +1 -0
- package/dist/bridge/messages/pageChanged.js +9 -0
- package/dist/bridge/messages/parentChanged.d.ts +22 -0
- package/dist/bridge/messages/parentChanged.d.ts.map +1 -0
- package/dist/bridge/messages/parentChanged.js +9 -0
- package/dist/bridge/messages/queryDataSource.d.ts +20 -0
- package/dist/bridge/messages/queryDataSource.d.ts.map +1 -0
- package/dist/bridge/messages/queryDataSource.js +19 -0
- package/dist/bridge/messages/queryDataSourceResult.d.ts +90 -0
- package/dist/bridge/messages/queryDataSourceResult.d.ts.map +1 -0
- package/dist/bridge/messages/queryDataSourceResult.js +21 -0
- package/dist/bridge/messages/ready.d.ts +45 -0
- package/dist/bridge/messages/ready.d.ts.map +1 -0
- package/dist/bridge/messages/ready.js +37 -0
- package/dist/bridge/messages/resize.d.ts +12 -0
- package/dist/bridge/messages/resize.d.ts.map +1 -0
- package/dist/bridge/messages/resize.js +10 -0
- package/dist/bridge/messages/sandboxToHost.d.ts +410 -0
- package/dist/bridge/messages/sandboxToHost.d.ts.map +1 -0
- package/dist/bridge/messages/sandboxToHost.js +25 -0
- package/dist/bridge/messages/themeChanged.d.ts +11 -0
- package/dist/bridge/messages/themeChanged.d.ts.map +1 -0
- package/dist/bridge/messages/themeChanged.js +10 -0
- package/dist/bridge/messages/updatePage.d.ts +171 -0
- package/dist/bridge/messages/updatePage.d.ts.map +1 -0
- package/dist/bridge/messages/updatePage.js +15 -0
- package/dist/bridge/messages/updatePageResult.d.ts +210 -0
- package/dist/bridge/messages/updatePageResult.d.ts.map +1 -0
- package/dist/bridge/messages/updatePageResult.js +27 -0
- package/dist/bridge/pages/page.d.ts +600 -0
- package/dist/bridge/pages/page.d.ts.map +1 -0
- package/dist/bridge/pages/page.js +217 -0
- package/dist/bridge/parent.d.ts +25 -0
- package/dist/bridge/parent.d.ts.map +1 -0
- package/dist/bridge/parent.js +11 -0
- package/dist/bridge/pendingRequests.d.ts +14 -0
- package/dist/bridge/pendingRequests.d.ts.map +1 -0
- package/dist/bridge/pendingRequests.js +27 -0
- package/dist/bridge/sandboxClient.d.ts +63 -0
- package/dist/bridge/sandboxClient.d.ts.map +1 -0
- package/dist/bridge/sandboxClient.js +92 -0
- package/dist/bridge/theme.d.ts +4 -0
- package/dist/bridge/theme.d.ts.map +1 -0
- package/dist/bridge/theme.js +2 -0
- package/dist/bridge/users/user.d.ts +36 -0
- package/dist/bridge/users/user.d.ts.map +1 -0
- package/dist/bridge/users/user.js +19 -0
- package/dist/customBlock.d.ts +36 -0
- package/dist/customBlock.d.ts.map +1 -0
- package/dist/customBlock.js +65 -0
- package/dist/host/createCustomBlockHost.d.ts +34 -0
- package/dist/host/createCustomBlockHost.d.ts.map +1 -0
- package/dist/host/createCustomBlockHost.js +278 -0
- package/dist/host/lifecycle/initErrors.d.ts +10 -0
- package/dist/host/lifecycle/initErrors.d.ts.map +1 -0
- package/dist/host/lifecycle/initErrors.js +123 -0
- package/dist/host/lifecycle/ready.d.ts +8 -0
- package/dist/host/lifecycle/ready.d.ts.map +1 -0
- package/dist/host/lifecycle/ready.js +24 -0
- package/dist/host/lifecycle/types.d.ts +24 -0
- package/dist/host/lifecycle/types.d.ts.map +1 -0
- package/dist/host/lifecycle/types.js +1 -0
- package/dist/host/messages/invalidSandboxMessage.d.ts +7 -0
- package/dist/host/messages/invalidSandboxMessage.d.ts.map +1 -0
- package/dist/host/messages/invalidSandboxMessage.js +24 -0
- package/dist/host/messages/types.d.ts +60 -0
- package/dist/host/messages/types.d.ts.map +1 -0
- package/dist/host/messages/types.js +1 -0
- package/dist/host/queries/querySubscriptions.d.ts +20 -0
- package/dist/host/queries/querySubscriptions.d.ts.map +1 -0
- package/dist/host/queries/querySubscriptions.js +29 -0
- package/dist/host/queries/types.d.ts +9 -0
- package/dist/host/queries/types.d.ts.map +1 -0
- package/dist/host/queries/types.js +1 -0
- package/dist/host.d.ts +73 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +42 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/init.d.ts +53 -0
- package/dist/init.d.ts.map +1 -0
- package/dist/init.js +87 -0
- package/dist/react/DebugMessageLog.d.ts +2 -0
- package/dist/react/DebugMessageLog.d.ts.map +1 -0
- package/dist/react/DebugMessageLog.js +22 -0
- package/dist/react/NotionCustomBlock.css +110 -0
- package/dist/react/NotionCustomBlock.d.ts +50 -0
- package/dist/react/NotionCustomBlock.d.ts.map +1 -0
- package/dist/react/NotionCustomBlock.js +81 -0
- package/dist/react/index.d.ts +14 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +13 -0
- package/dist/react/standalonePreview.d.ts +2 -0
- package/dist/react/standalonePreview.d.ts.map +1 -0
- package/dist/react/standalonePreview.js +26 -0
- package/dist/react/useCustomBlockAutoResize.d.ts +30 -0
- package/dist/react/useCustomBlockAutoResize.d.ts.map +1 -0
- package/dist/react/useCustomBlockAutoResize.js +35 -0
- package/dist/react/useCustomBlockInit.d.ts +43 -0
- package/dist/react/useCustomBlockInit.d.ts.map +1 -0
- package/dist/react/useCustomBlockInit.js +60 -0
- package/dist/react/useDataSource.d.ts +13 -0
- package/dist/react/useDataSource.d.ts.map +1 -0
- package/dist/react/useDataSource.js +37 -0
- package/dist/react/useHostState.d.ts +2 -0
- package/dist/react/useHostState.d.ts.map +1 -0
- package/dist/react/useHostState.js +5 -0
- package/dist/react/useRuntimeState.d.ts +66 -0
- package/dist/react/useRuntimeState.d.ts.map +1 -0
- package/dist/react/useRuntimeState.js +73 -0
- package/dist/types.d.ts +154 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +10 -0
- package/dist/version.d.ts +9 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +7 -0
- package/docs/block-location.md +83 -0
- package/docs/data-sources.md +186 -0
- package/docs/lifecycle.md +172 -0
- package/docs/manifest.md +42 -0
- package/docs/pages.md +143 -0
- package/docs/users.md +92 -0
- package/package.json +69 -0
- package/src/autoResize.ts +84 -0
- package/src/bridge/SandboxBridge.ts +921 -0
- package/src/bridge/dataSources/dataSource.ts +63 -0
- package/src/bridge/dataSources/dataSourcePage.ts +71 -0
- package/src/bridge/dataSources/dataSourceValue.ts +19 -0
- package/src/bridge/dataSources/dateValue.ts +96 -0
- package/src/bridge/dataSources/errors.ts +14 -0
- package/src/bridge/dataSources/propertySchema.ts +186 -0
- package/src/bridge/dataSources/recordPointer.ts +13 -0
- package/src/bridge/dataSources/resolve.ts +99 -0
- package/src/bridge/dataSources/resolveProperty.ts +130 -0
- package/src/bridge/errors.ts +13 -0
- package/src/bridge/hostState.ts +154 -0
- package/src/bridge/ids.ts +58 -0
- package/src/bridge/incomingType.ts +19 -0
- package/src/bridge/loadManifest.ts +89 -0
- package/src/bridge/manifest.ts +53 -0
- package/src/bridge/messages/createPage.ts +67 -0
- package/src/bridge/messages/createPageResult.ts +52 -0
- package/src/bridge/messages/currentUserChanged.ts +14 -0
- package/src/bridge/messages/dataSourcesChanged.ts +18 -0
- package/src/bridge/messages/getPage.ts +52 -0
- package/src/bridge/messages/getUser.ts +48 -0
- package/src/bridge/messages/hostToSandbox.ts +37 -0
- package/src/bridge/messages/init.ts +81 -0
- package/src/bridge/messages/invalidHostMessage.ts +16 -0
- package/src/bridge/messages/invalidSandboxMessage.ts +18 -0
- package/src/bridge/messages/listUsers.ts +49 -0
- package/src/bridge/messages/pageChanged.ts +12 -0
- package/src/bridge/messages/parentChanged.ts +14 -0
- package/src/bridge/messages/queryDataSource.ts +24 -0
- package/src/bridge/messages/queryDataSourceResult.ts +38 -0
- package/src/bridge/messages/ready.ts +41 -0
- package/src/bridge/messages/resize.ts +13 -0
- package/src/bridge/messages/sandboxToHost.ts +30 -0
- package/src/bridge/messages/themeChanged.ts +15 -0
- package/src/bridge/messages/updatePage.ts +22 -0
- package/src/bridge/messages/updatePageResult.ts +49 -0
- package/src/bridge/pages/page.ts +281 -0
- package/src/bridge/parent.ts +27 -0
- package/src/bridge/pendingRequests.ts +28 -0
- package/src/bridge/sandboxClient.ts +137 -0
- package/src/bridge/theme.ts +5 -0
- package/src/bridge/users/user.ts +31 -0
- package/src/css.d.ts +1 -0
- package/src/customBlock.ts +102 -0
- package/src/host/createCustomBlockHost.ts +392 -0
- package/src/host/lifecycle/initErrors.ts +132 -0
- package/src/host/lifecycle/ready.ts +36 -0
- package/src/host/lifecycle/types.ts +28 -0
- package/src/host/messages/invalidSandboxMessage.ts +38 -0
- package/src/host/messages/types.ts +67 -0
- package/src/host/queries/querySubscriptions.ts +52 -0
- package/src/host/queries/types.ts +16 -0
- package/src/host.ts +167 -0
- package/src/index.ts +115 -0
- package/src/init.ts +143 -0
- package/src/react/DebugMessageLog.tsx +30 -0
- package/src/react/NotionCustomBlock.css +110 -0
- package/src/react/NotionCustomBlock.tsx +151 -0
- package/src/react/index.ts +28 -0
- package/src/react/standalonePreview.ts +28 -0
- package/src/react/useCustomBlockAutoResize.ts +46 -0
- package/src/react/useCustomBlockInit.ts +91 -0
- package/src/react/useDataSource.ts +47 -0
- package/src/react/useHostState.ts +9 -0
- package/src/react/useRuntimeState.ts +85 -0
- package/src/types.ts +175 -0
- package/src/utils.ts +13 -0
- package/src/version.ts +8 -0
- package/vite-plugin/index.d.ts +46 -0
- package/vite-plugin/index.js +115 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { type ReactNode, useEffect, useState } from "react"
|
|
2
|
+
import { type InitCustomBlockOptions, NotInIframeError } from "../index.js"
|
|
3
|
+
import { DebugMessageLog } from "./DebugMessageLog.js"
|
|
4
|
+
import { seedStandalonePreviewState } from "./standalonePreview.js"
|
|
5
|
+
import { useCustomBlockAutoResize } from "./useCustomBlockAutoResize.js"
|
|
6
|
+
import { useCustomBlockInit } from "./useCustomBlockInit.js"
|
|
7
|
+
import { useCustomBlockHost } from "./useHostState.js"
|
|
8
|
+
import "./NotionCustomBlock.css"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Props accepted by {@link NotionCustomBlock}.
|
|
12
|
+
*/
|
|
13
|
+
export type NotionCustomBlockProps = InitCustomBlockOptions & {
|
|
14
|
+
children: ReactNode
|
|
15
|
+
/**
|
|
16
|
+
* Rendered while the SDK ↔ host handshake is in progress. Defaults to
|
|
17
|
+
* `null` (nothing).
|
|
18
|
+
*/
|
|
19
|
+
fallback?: ReactNode
|
|
20
|
+
/**
|
|
21
|
+
* Rendered when the handshake fails. Either a node, or a function that
|
|
22
|
+
* receives the `Error`. When omitted, a friendly default error card is
|
|
23
|
+
* rendered with developer details — replace it for production templates.
|
|
24
|
+
*/
|
|
25
|
+
errorFallback?: ReactNode | ((error: Error) => ReactNode)
|
|
26
|
+
/**
|
|
27
|
+
* Whether the provider should automatically post resize messages so the
|
|
28
|
+
* host iframe matches the content height of `#root`. Defaults to `true`.
|
|
29
|
+
* Pass `false` when you want to use the default block size and are ok
|
|
30
|
+
* with scrollbars within the Notion client.
|
|
31
|
+
*
|
|
32
|
+
* @default true
|
|
33
|
+
*/
|
|
34
|
+
autoResize?: boolean
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Top-level wrapper that runs the SDK ↔ host handshake and gates `children`
|
|
39
|
+
* until it resolves. Passes `timeoutMs` straight through to
|
|
40
|
+
* {@link initCustomBlock}.
|
|
41
|
+
*
|
|
42
|
+
* Templates that prefer not to write a `Root` gating component (or top-level
|
|
43
|
+
* `await`) can mount their app entirely inside this provider:
|
|
44
|
+
*
|
|
45
|
+
* ```tsx
|
|
46
|
+
* ReactDOM.createRoot(root).render(
|
|
47
|
+
* <NotionCustomBlock>
|
|
48
|
+
* <App />
|
|
49
|
+
* </NotionCustomBlock>,
|
|
50
|
+
* )
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* Inside `children`, every SDK hook is guaranteed to return a populated
|
|
54
|
+
* value. Outside the provider (or during the loading window), they throw.
|
|
55
|
+
*/
|
|
56
|
+
export function NotionCustomBlock({
|
|
57
|
+
children,
|
|
58
|
+
timeoutMs,
|
|
59
|
+
fallback = null,
|
|
60
|
+
errorFallback,
|
|
61
|
+
autoResize = true,
|
|
62
|
+
}: NotionCustomBlockProps) {
|
|
63
|
+
const init = useCustomBlockInit({ timeoutMs })
|
|
64
|
+
useCustomBlockAutoResize({ enabled: autoResize })
|
|
65
|
+
const isStandalone = init.error instanceof NotInIframeError
|
|
66
|
+
const host = useCustomBlockHost()
|
|
67
|
+
const [debugOpen, setDebugOpen] = useState(false)
|
|
68
|
+
|
|
69
|
+
useEffect(() => {
|
|
70
|
+
const onKeyDown = (e: KeyboardEvent) => {
|
|
71
|
+
if (e.key === "\\") {
|
|
72
|
+
setDebugOpen(prev => !prev)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
window.addEventListener("keydown", onKeyDown)
|
|
76
|
+
return () => window.removeEventListener("keydown", onKeyDown)
|
|
77
|
+
}, [])
|
|
78
|
+
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
if (!isStandalone) {
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
console.warn(`[notion-custom-sdk] ${init.error?.message}`)
|
|
84
|
+
seedStandalonePreviewState()
|
|
85
|
+
}, [isStandalone, init.error])
|
|
86
|
+
|
|
87
|
+
if (debugOpen) {
|
|
88
|
+
return <DebugMessageLog />
|
|
89
|
+
}
|
|
90
|
+
if (init.error && !isStandalone) {
|
|
91
|
+
if (errorFallback === undefined) {
|
|
92
|
+
return <DefaultInitErrorFallback error={init.error} />
|
|
93
|
+
}
|
|
94
|
+
return (
|
|
95
|
+
<>
|
|
96
|
+
{typeof errorFallback === "function"
|
|
97
|
+
? errorFallback(init.error)
|
|
98
|
+
: errorFallback}
|
|
99
|
+
</>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
if (isStandalone) {
|
|
103
|
+
// Wait for the effect to seed placeholder host state; otherwise hooks
|
|
104
|
+
// in `children` would throw.
|
|
105
|
+
if (host.status !== "initialized") {
|
|
106
|
+
return <>{fallback}</>
|
|
107
|
+
}
|
|
108
|
+
return (
|
|
109
|
+
<>
|
|
110
|
+
<div role="status" className="ncblock-standalone-banner">
|
|
111
|
+
Notion host not detected — running in standalone preview. SDK hooks
|
|
112
|
+
return placeholder values until embedded in Notion.
|
|
113
|
+
</div>
|
|
114
|
+
{children}
|
|
115
|
+
</>
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
if (!init.isLoaded) {
|
|
119
|
+
return <>{fallback}</>
|
|
120
|
+
}
|
|
121
|
+
return <>{children}</>
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// TODO(custom-blocks): Align the styling of this with the host-side error states.
|
|
125
|
+
function DefaultInitErrorFallback({ error }: { error: Error }) {
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
console.warn(
|
|
128
|
+
`[notion-custom-sdk] Custom block init failed: ${error.message}`,
|
|
129
|
+
)
|
|
130
|
+
}, [error])
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<div role="alert" className="ncblock-default-init-error">
|
|
134
|
+
<div className="ncblock-default-init-error__card">
|
|
135
|
+
<div className="ncblock-default-init-error__eyebrow">Custom block</div>
|
|
136
|
+
<h2 className="ncblock-default-init-error__title">
|
|
137
|
+
Couldn't connect to Notion
|
|
138
|
+
</h2>
|
|
139
|
+
<p className="ncblock-default-init-error__body">
|
|
140
|
+
This custom block loaded, but the setup handshake didn't finish.
|
|
141
|
+
Try again from Notion. If this keeps happening, check the browser
|
|
142
|
+
console for SDK details.
|
|
143
|
+
</p>
|
|
144
|
+
<details className="ncblock-default-init-error__details">
|
|
145
|
+
<summary>Developer details</summary>
|
|
146
|
+
<pre className="ncblock-default-init-error__pre">{error.message}</pre>
|
|
147
|
+
</details>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
)
|
|
151
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React entrypoint for `@notionhq/custom-blocks/react`.
|
|
3
|
+
*
|
|
4
|
+
* Exposes only the React surface — components and hooks. Framework-neutral
|
|
5
|
+
* values and types (clients, manifest/data-source types, etc.) live on the
|
|
6
|
+
* `@notionhq/custom-blocks` entrypoint and are intentionally NOT re-exported
|
|
7
|
+
* here, so the two public surfaces stay disjoint.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
NotionCustomBlock,
|
|
12
|
+
type NotionCustomBlockProps,
|
|
13
|
+
} from "./NotionCustomBlock.js"
|
|
14
|
+
export { useCustomBlockAutoResize } from "./useCustomBlockAutoResize.js"
|
|
15
|
+
export {
|
|
16
|
+
type CustomBlockInitFailure,
|
|
17
|
+
type UseCustomBlockInitResult,
|
|
18
|
+
useCustomBlockInit,
|
|
19
|
+
} from "./useCustomBlockInit.js"
|
|
20
|
+
export { useDataSource } from "./useDataSource.js"
|
|
21
|
+
export {
|
|
22
|
+
useBlockId,
|
|
23
|
+
useCurrentUser,
|
|
24
|
+
useManifest,
|
|
25
|
+
usePage,
|
|
26
|
+
useParent,
|
|
27
|
+
useTheme,
|
|
28
|
+
} from "./useRuntimeState.js"
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as v from "valibot"
|
|
2
|
+
import { notionBlockIdSchema, notionPageIdSchema } from "../bridge/ids.js"
|
|
3
|
+
import { customBlockHost } from "../bridge/sandboxClient.js"
|
|
4
|
+
|
|
5
|
+
const previewBlockId = v.parse(notionBlockIdSchema, "")
|
|
6
|
+
const previewPageId = v.parse(notionPageIdSchema, "")
|
|
7
|
+
|
|
8
|
+
export function seedStandalonePreviewState() {
|
|
9
|
+
customBlockHost.setMockState({
|
|
10
|
+
type: "init",
|
|
11
|
+
status: "success",
|
|
12
|
+
theme: "light",
|
|
13
|
+
blockId: previewBlockId,
|
|
14
|
+
parent: { type: "page_id", page_id: previewPageId },
|
|
15
|
+
page: { id: previewPageId },
|
|
16
|
+
dataSources: { bindings: {} },
|
|
17
|
+
currentUser: {
|
|
18
|
+
object: "user",
|
|
19
|
+
id: "",
|
|
20
|
+
name: "Preview User",
|
|
21
|
+
avatar_url: null,
|
|
22
|
+
type: "person",
|
|
23
|
+
person: {
|
|
24
|
+
email: "preview@example.com",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
})
|
|
28
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useEffect } from "react"
|
|
2
|
+
import { customBlock } from "../index.js"
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Measures the sandbox's `#root` element and posts `resize` messages so the host iframe
|
|
6
|
+
* matches the block's border-box height. Unchanged values are deduped.
|
|
7
|
+
*
|
|
8
|
+
* `<NotionCustomBlock>` calls this hook for you by default — only reach for it directly
|
|
9
|
+
* when you need to drive `enabled` yourself (e.g. behind a debug toggle). In that case,
|
|
10
|
+
* pass `autoResize={false}` to the provider to avoid running it twice. For full-bleed
|
|
11
|
+
* views that should fill their slot, pass `autoResize={false}` and skip the hook.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* <NotionCustomBlock autoResize={false}>
|
|
15
|
+
* <App />
|
|
16
|
+
* </NotionCustomBlock>
|
|
17
|
+
*
|
|
18
|
+
* function App() {
|
|
19
|
+
* const [enabled, setEnabled] = useState(true)
|
|
20
|
+
* useCustomBlockAutoResize({ enabled })
|
|
21
|
+
* return <div>…</div>
|
|
22
|
+
* }
|
|
23
|
+
*/
|
|
24
|
+
export function useCustomBlockAutoResize(
|
|
25
|
+
args: {
|
|
26
|
+
/**
|
|
27
|
+
* Whether or not the hook is enabled. To disable this behavior, pass `false`. This is
|
|
28
|
+
* provided as an argument to allow for conditional disabling of the hook.
|
|
29
|
+
*
|
|
30
|
+
* @default true
|
|
31
|
+
*/
|
|
32
|
+
enabled?: boolean
|
|
33
|
+
} = {},
|
|
34
|
+
): void {
|
|
35
|
+
const { enabled = true } = args
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (!enabled) {
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
if (typeof window === "undefined") {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
const target = document.getElementById("root")
|
|
44
|
+
return customBlock.autoResize({ target })
|
|
45
|
+
}, [enabled])
|
|
46
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { useEffect, useState } from "react"
|
|
2
|
+
import { CustomBlockInitError } from "../bridge/messages/init.js"
|
|
3
|
+
import {
|
|
4
|
+
type CustomBlockInitial,
|
|
5
|
+
type InitCustomBlockOptions,
|
|
6
|
+
initCustomBlock,
|
|
7
|
+
NotInIframeError,
|
|
8
|
+
} from "../init.js"
|
|
9
|
+
|
|
10
|
+
export type CustomBlockInitFailure = CustomBlockInitError | NotInIframeError
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Discriminated state returned by {@link useCustomBlockInit}.
|
|
14
|
+
*
|
|
15
|
+
* Branch on `isLoaded`/`error`:
|
|
16
|
+
* - `{ isLoaded: false, error: undefined }` — handshake in progress.
|
|
17
|
+
* - `{ isLoaded: false, error: CustomBlockInitFailure }` — handshake failed (most commonly a
|
|
18
|
+
* `CustomBlockInitError` with code `init_timeout` because the host never sent `init`).
|
|
19
|
+
* - `{ isLoaded: true, initial }` — handshake complete; safe to render
|
|
20
|
+
* children that call `useTheme`, `useBlockId`, etc.
|
|
21
|
+
*/
|
|
22
|
+
export type UseCustomBlockInitResult =
|
|
23
|
+
| { isLoaded: false; error: undefined }
|
|
24
|
+
| { isLoaded: false; error: CustomBlockInitFailure }
|
|
25
|
+
| { isLoaded: true; error: undefined; initial: CustomBlockInitial }
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* React wrapper around {@link initCustomBlock}. Kicks off the SDK ↔ host
|
|
29
|
+
* handshake on mount and returns a discriminated state object so the rest of
|
|
30
|
+
* the tree can render inside the `isLoaded === true` branch (where every
|
|
31
|
+
* other SDK hook is guaranteed to return a populated value).
|
|
32
|
+
*
|
|
33
|
+
* Idempotent — multiple components can call this; they share the same
|
|
34
|
+
* underlying handshake promise.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* function Root() {
|
|
38
|
+
* const init = useCustomBlockInit()
|
|
39
|
+
* if (init.error) return <p role="alert">Init failed: {init.error.message}</p>
|
|
40
|
+
* if (!init.isLoaded) return null
|
|
41
|
+
* return <App />
|
|
42
|
+
* }
|
|
43
|
+
*/
|
|
44
|
+
export function useCustomBlockInit(
|
|
45
|
+
opts?: InitCustomBlockOptions,
|
|
46
|
+
): UseCustomBlockInitResult {
|
|
47
|
+
const [state, setState] = useState<UseCustomBlockInitResult>({
|
|
48
|
+
isLoaded: false,
|
|
49
|
+
error: undefined,
|
|
50
|
+
})
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
let cancelled = false
|
|
53
|
+
initCustomBlock(opts).then(
|
|
54
|
+
initial => {
|
|
55
|
+
if (!cancelled) {
|
|
56
|
+
setState({ isLoaded: true, error: undefined, initial })
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
err => {
|
|
60
|
+
if (!cancelled) {
|
|
61
|
+
setState({
|
|
62
|
+
isLoaded: false,
|
|
63
|
+
error: normalizeInitError(err),
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
)
|
|
68
|
+
return () => {
|
|
69
|
+
cancelled = true
|
|
70
|
+
}
|
|
71
|
+
// `initCustomBlock` caches its result, so options after the first call
|
|
72
|
+
// are ignored — re-running on opts changes would be misleading.
|
|
73
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
74
|
+
}, [])
|
|
75
|
+
return state
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function normalizeInitError(error: unknown): CustomBlockInitFailure {
|
|
79
|
+
if (
|
|
80
|
+
error instanceof CustomBlockInitError ||
|
|
81
|
+
error instanceof NotInIframeError
|
|
82
|
+
) {
|
|
83
|
+
return error
|
|
84
|
+
}
|
|
85
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
86
|
+
return new CustomBlockInitError({
|
|
87
|
+
code: "unknown_error",
|
|
88
|
+
message,
|
|
89
|
+
isRetryable: false,
|
|
90
|
+
})
|
|
91
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useEffect } from "react"
|
|
2
|
+
import { customBlockDataSources } from "../bridge/sandboxClient.js"
|
|
3
|
+
import type { UseDataSourceOptions, UseDataSourceResult } from "../types.js"
|
|
4
|
+
import { useCustomBlockHost } from "./useHostState.js"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Reads from the data source mapped to the given semantic `key`.
|
|
8
|
+
*
|
|
9
|
+
* @param key - The semantic data-source key the block is wired to (e.g. `"people"`).
|
|
10
|
+
* @param options - Optional live snapshot options. `limit` defaults to 20 and
|
|
11
|
+
* is capped at 999.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const { items, isLoading, hasMore, error } = useDataSource("default", { limit: 25 })
|
|
15
|
+
*/
|
|
16
|
+
export function useDataSource(
|
|
17
|
+
key: string,
|
|
18
|
+
options?: UseDataSourceOptions,
|
|
19
|
+
): UseDataSourceResult {
|
|
20
|
+
const host = useCustomBlockHost()
|
|
21
|
+
const limit = options?.limit
|
|
22
|
+
const matchingDataSource =
|
|
23
|
+
host.status === "initialized"
|
|
24
|
+
? host.dataSources.find(dataSource => dataSource.key === key)
|
|
25
|
+
: undefined
|
|
26
|
+
|
|
27
|
+
const isInitialized = host.status === "initialized"
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!isInitialized) {
|
|
30
|
+
return
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
customBlockDataSources.query(key, { limit })
|
|
34
|
+
}, [matchingDataSource, isInitialized, key, limit])
|
|
35
|
+
|
|
36
|
+
const view = customBlockDataSources.getView(host, key)
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
items: view.items,
|
|
40
|
+
collectionSchema: view.collectionSchema,
|
|
41
|
+
propertySchemasById: view.propertySchemasById,
|
|
42
|
+
propertySchemasByKey: view.propertySchemasByKey,
|
|
43
|
+
isLoading: view.isLoading,
|
|
44
|
+
hasMore: view.hasMore,
|
|
45
|
+
error: view.error,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { useSyncExternalStore } from "react"
|
|
2
|
+
import type { NotionBlockId } from "../bridge/ids.js"
|
|
3
|
+
import type { CustomBlockManifest } from "../bridge/manifest.js"
|
|
4
|
+
import type { CustomBlockPage } from "../bridge/pages/page.js"
|
|
5
|
+
import type { NotionParent } from "../bridge/parent.js"
|
|
6
|
+
import type { NotionTheme } from "../bridge/theme.js"
|
|
7
|
+
import type { NotionUser } from "../bridge/users/user.js"
|
|
8
|
+
import { customBlock } from "../customBlock.js"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Returns this custom block's ID. This is stable throughout the block's lifetime.
|
|
12
|
+
*
|
|
13
|
+
* Throws if called before `initCustomBlock` has resolved.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* const blockId = useBlockId()
|
|
17
|
+
*/
|
|
18
|
+
export function useBlockId(): NotionBlockId {
|
|
19
|
+
return useSyncExternalStore(customBlock.subscribe, customBlock.getBlockId)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Returns the block's parent in the document tree. Re-renders when the host sends
|
|
24
|
+
* a parent location update (e.g. the block moves into a different container).
|
|
25
|
+
*
|
|
26
|
+
* Throws if called before `initCustomBlock` has resolved.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* const parent = useParent()
|
|
30
|
+
*/
|
|
31
|
+
export function useParent(): NotionParent {
|
|
32
|
+
return useSyncExternalStore(customBlock.subscribe, customBlock.getParent)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Returns the nearest enclosing page ancestor. Re-renders when the host sends
|
|
37
|
+
* a page location update.
|
|
38
|
+
*
|
|
39
|
+
* Throws if called before `initCustomBlock` has resolved.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* const page = usePage()
|
|
43
|
+
*/
|
|
44
|
+
export function usePage(): CustomBlockPage {
|
|
45
|
+
return useSyncExternalStore(customBlock.subscribe, customBlock.getPage)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Returns the host's current theme. Re-renders on every `themeChanged` message from the host.
|
|
50
|
+
*
|
|
51
|
+
* Throws if called before `initCustomBlock` has resolved.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* const theme = useTheme()
|
|
55
|
+
*/
|
|
56
|
+
export function useTheme(): NotionTheme {
|
|
57
|
+
return useSyncExternalStore(customBlock.subscribe, customBlock.getTheme)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Returns the viewing user's Notion profile. Re-renders whenever the host sends a
|
|
62
|
+
* `currentUserChanged` message.
|
|
63
|
+
*
|
|
64
|
+
* Throws if called before `initCustomBlock` has resolved. `await` it before mounting.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* const me = useCurrentUser()
|
|
68
|
+
* console.log(me.id, me.name, me.person.email)
|
|
69
|
+
*/
|
|
70
|
+
export function useCurrentUser(): NotionUser {
|
|
71
|
+
return useSyncExternalStore(customBlock.subscribe, customBlock.getCurrentUser)
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Returns the author-declared manifest loaded from `custom_blocks.json` — the semantic
|
|
76
|
+
* data-source keys plus their declared `name`, `description`, and property declarations.
|
|
77
|
+
* `null` when the block ships no manifest.
|
|
78
|
+
*
|
|
79
|
+
* This is the configuration the block declared, not host-resolved bindings: use
|
|
80
|
+
* `useDataSource(key)` for rows and resolved schema. Handy for enumerating the declared
|
|
81
|
+
* data-source keys (e.g. picking a default key, or rendering a key switcher).
|
|
82
|
+
*/
|
|
83
|
+
export function useManifest(): CustomBlockManifest | null {
|
|
84
|
+
return useSyncExternalStore(customBlock.subscribe, customBlock.getManifest)
|
|
85
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import type { NotionCollectionSchema } from "./bridge/dataSources/dataSource.js"
|
|
2
|
+
import type {
|
|
3
|
+
NotionDataSourcePage,
|
|
4
|
+
NotionDataSourcePageUpdateInput,
|
|
5
|
+
NotionDataSourcePageUpdateResult,
|
|
6
|
+
} from "./bridge/dataSources/dataSourcePage.js"
|
|
7
|
+
import type { NotionPropertySchema } from "./bridge/dataSources/propertySchema.js"
|
|
8
|
+
import type { CustomBlockErrorInfo } from "./bridge/errors.js"
|
|
9
|
+
import type { NotionDataSourceId } from "./bridge/ids.js"
|
|
10
|
+
import type { NotionCreatePagePosition } from "./bridge/messages/createPage.js"
|
|
11
|
+
import type { CustomBlockCreatePageErrorInfo } from "./bridge/messages/createPageResult.js"
|
|
12
|
+
import type { CustomBlockGetPageErrorInfo } from "./bridge/messages/getPage.js"
|
|
13
|
+
import type { CustomBlockGetUserErrorInfo } from "./bridge/messages/getUser.js"
|
|
14
|
+
import type { CustomBlockListUsersErrorInfo } from "./bridge/messages/listUsers.js"
|
|
15
|
+
import type { CustomBlockQueryDataSourceErrorInfo } from "./bridge/messages/queryDataSourceResult.js"
|
|
16
|
+
import type { CustomBlockUpdatePageErrorInfo } from "./bridge/messages/updatePageResult.js"
|
|
17
|
+
import type {
|
|
18
|
+
NotionPage,
|
|
19
|
+
NotionPageCover,
|
|
20
|
+
NotionPageIcon,
|
|
21
|
+
NotionPageId,
|
|
22
|
+
NotionPagePropertyInputMap,
|
|
23
|
+
NotionPagePropertyWriteMap,
|
|
24
|
+
} from "./bridge/pages/page.js"
|
|
25
|
+
import type { NotionUser, NotionUserList } from "./bridge/users/user.js"
|
|
26
|
+
|
|
27
|
+
export type { NotionDataSourceId, NotionSpaceId } from "./bridge/ids.js"
|
|
28
|
+
export type { NotionPageId } from "./bridge/pages/page.js"
|
|
29
|
+
export type {
|
|
30
|
+
NotionUser,
|
|
31
|
+
NotionUserId,
|
|
32
|
+
NotionUserList,
|
|
33
|
+
} from "./bridge/users/user.js"
|
|
34
|
+
export type {
|
|
35
|
+
CustomBlockCreatePageErrorInfo,
|
|
36
|
+
CustomBlockErrorInfo,
|
|
37
|
+
CustomBlockGetPageErrorInfo,
|
|
38
|
+
CustomBlockGetUserErrorInfo,
|
|
39
|
+
CustomBlockListUsersErrorInfo,
|
|
40
|
+
CustomBlockQueryDataSourceErrorInfo,
|
|
41
|
+
CustomBlockUpdatePageErrorInfo,
|
|
42
|
+
NotionDataSourcePageUpdateInput,
|
|
43
|
+
NotionDataSourcePageUpdateResult,
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Return shape of `useDataSource`.
|
|
48
|
+
*
|
|
49
|
+
* - `items` — the rows the host has returned so far. Empty until the first response arrives.
|
|
50
|
+
* - `isLoading` — `true` while a query is in flight.
|
|
51
|
+
* - `hasMore` — `true` if the host indicated more rows are available beyond the current page.
|
|
52
|
+
* - `error` — structured error information if the most recent query failed.
|
|
53
|
+
*/
|
|
54
|
+
export type UseDataSourceResult = {
|
|
55
|
+
items: NotionDataSourcePage[]
|
|
56
|
+
/**
|
|
57
|
+
* Collection/data-source schema for the bound Notion data source, including raw property
|
|
58
|
+
* schemas. Undefined when the semantic data-source key has not been bound.
|
|
59
|
+
*/
|
|
60
|
+
collectionSchema?: NotionCollectionSchema
|
|
61
|
+
/**
|
|
62
|
+
* Per-property schemas keyed by raw property ID, including the four synthetic built-ins
|
|
63
|
+
* (`created_time`, `last_edited_time`, `created_by`, `last_edited_by`).
|
|
64
|
+
*/
|
|
65
|
+
propertySchemasById: { [propertyId: string]: NotionPropertySchema }
|
|
66
|
+
/**
|
|
67
|
+
* Per-property schemas keyed by user-defined keys from the data source's `propertyIdsByKey`.
|
|
68
|
+
* Built-ins are NOT included here. Keys mapped to `undefined` indicate a declared-but-unbound
|
|
69
|
+
* slot.
|
|
70
|
+
*/
|
|
71
|
+
propertySchemasByKey: { [key: string]: NotionPropertySchema | undefined }
|
|
72
|
+
isLoading: boolean
|
|
73
|
+
hasMore: boolean
|
|
74
|
+
error?: CustomBlockQueryDataSourceErrorInfo
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export type UseDataSourceOptions = {
|
|
78
|
+
/**
|
|
79
|
+
* Maximum number of rows to request from the host. Defaults to 20.
|
|
80
|
+
*/
|
|
81
|
+
limit?: number
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Parent reference accepted by `sdk.pages.create`. Mirrors Notion's public `POST /v1/pages`
|
|
86
|
+
* parent shape; see https://developers.notion.com/reference/data-source.
|
|
87
|
+
*
|
|
88
|
+
* - `page_id`: Create a child page under the given Notion page.
|
|
89
|
+
* - `data_source_id`: Create a row inside the given Notion data source (aka the internal
|
|
90
|
+
* collection). The public API's `data_source_id` is the same UUID as the `collectionPointer.id`
|
|
91
|
+
* exposed in `dataSources`, so either value works here.
|
|
92
|
+
* - `data_source_key`: Create a row inside the data source that the custom block was configured with
|
|
93
|
+
* under this semantic key. The SDK resolves the key to a `data_source_id` locally before
|
|
94
|
+
* sending the request to the host.
|
|
95
|
+
*/
|
|
96
|
+
export type CreatePageParent =
|
|
97
|
+
| { type: "page_id"; page_id: NotionPageId }
|
|
98
|
+
| { type: "data_source_id"; data_source_id: NotionDataSourceId }
|
|
99
|
+
| { type: "data_source_key"; key: string }
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Input accepted by `sdk.pages.create`. Mirrors the Notion public API `POST /v1/pages` API.
|
|
103
|
+
*/
|
|
104
|
+
export type CreatePageInput = {
|
|
105
|
+
parent: CreatePageParent
|
|
106
|
+
properties: NotionPagePropertyInputMap
|
|
107
|
+
icon?: NotionPageIcon
|
|
108
|
+
cover?: NotionPageCover
|
|
109
|
+
position?: NotionCreatePagePosition
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The result of a `sdk.pages.create` API call.
|
|
114
|
+
*/
|
|
115
|
+
export type CreatePageResult =
|
|
116
|
+
| {
|
|
117
|
+
status: "success"
|
|
118
|
+
/** The newly created page. */
|
|
119
|
+
page: NotionPage
|
|
120
|
+
}
|
|
121
|
+
| { status: "error"; error: CustomBlockCreatePageErrorInfo }
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Input accepted by `sdk.pages.update`.
|
|
125
|
+
*
|
|
126
|
+
* `properties` is keyed by raw Notion property ID. To update a row with configured
|
|
127
|
+
* custom-block property keys, use the `update` helper on pages returned from
|
|
128
|
+
* `useDataSource`.
|
|
129
|
+
*/
|
|
130
|
+
export type UpdatePageInput = {
|
|
131
|
+
pageId: NotionPageId
|
|
132
|
+
properties?: NotionPagePropertyWriteMap
|
|
133
|
+
icon?: NotionPageIcon
|
|
134
|
+
cover?: NotionPageCover
|
|
135
|
+
archived?: boolean
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Result of `sdk.pages.get`.
|
|
140
|
+
*/
|
|
141
|
+
export type GetPageResult =
|
|
142
|
+
| {
|
|
143
|
+
status: "success"
|
|
144
|
+
page: NotionPage
|
|
145
|
+
}
|
|
146
|
+
| { status: "error"; error: CustomBlockGetPageErrorInfo }
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Result of `sdk.pages.update` / `sdk.pages.delete`.
|
|
150
|
+
*/
|
|
151
|
+
export type UpdatePageResult =
|
|
152
|
+
| {
|
|
153
|
+
status: "success"
|
|
154
|
+
page: NotionPage
|
|
155
|
+
}
|
|
156
|
+
| { status: "error"; error: CustomBlockUpdatePageErrorInfo }
|
|
157
|
+
|
|
158
|
+
export type ListUsersInput = {
|
|
159
|
+
startCursor?: string
|
|
160
|
+
pageSize?: number
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export type ListUsersResult =
|
|
164
|
+
| {
|
|
165
|
+
status: "success"
|
|
166
|
+
list: NotionUserList
|
|
167
|
+
}
|
|
168
|
+
| { status: "error"; error: CustomBlockListUsersErrorInfo }
|
|
169
|
+
|
|
170
|
+
export type GetUserResult =
|
|
171
|
+
| {
|
|
172
|
+
status: "success"
|
|
173
|
+
user: NotionUser
|
|
174
|
+
}
|
|
175
|
+
| { status: "error"; error: CustomBlockGetUserErrorInfo }
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal helpers shared across the SDK.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Throws an error when an unexpected value is encountered. This is used to ensure all code paths
|
|
7
|
+
* are covered when using discriminated unions.
|
|
8
|
+
*/
|
|
9
|
+
export function unreachable(value: never): never {
|
|
10
|
+
throw new Error(
|
|
11
|
+
`[notion-custom-sdk] Unexpected value encountered: ${JSON.stringify(value)}`,
|
|
12
|
+
)
|
|
13
|
+
}
|
package/src/version.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime SDK package version. Sent over the bridge for host-side analytics only. Business logic
|
|
3
|
+
* should compare against the bridge protocol version instead of this value.
|
|
4
|
+
*
|
|
5
|
+
* This checked-in value intentionally stays generic for local development. The SDK publish build
|
|
6
|
+
* overwrites the compiled runtime module with package.json's semver before publishing.
|
|
7
|
+
*/
|
|
8
|
+
export const NCBLOCK_SDK_VERSION: string = "0.0.0"
|