@notionhq/custom-blocks 0.0.76 → 0.0.78

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 (109) hide show
  1. package/HOST.md +68 -37
  2. package/bin/src/bridge/manifest.js +3 -3
  3. package/dist/bridge/SandboxBridge.d.ts +6 -12
  4. package/dist/bridge/SandboxBridge.d.ts.map +1 -1
  5. package/dist/bridge/SandboxBridge.js +123 -71
  6. package/dist/bridge/dataSources/resolve.d.ts +3 -4
  7. package/dist/bridge/dataSources/resolve.d.ts.map +1 -1
  8. package/dist/bridge/dataSources/resolve.js +2 -12
  9. package/dist/bridge/hostState.d.ts +3 -2
  10. package/dist/bridge/hostState.d.ts.map +1 -1
  11. package/dist/bridge/loadManifest.d.ts +4 -4
  12. package/dist/bridge/loadManifest.d.ts.map +1 -1
  13. package/dist/bridge/loadManifest.js +2 -2
  14. package/dist/bridge/manifest.d.ts +3 -3
  15. package/dist/bridge/manifest.js +3 -3
  16. package/dist/bridge/messages/{ready.d.ts → connect.d.ts} +13 -11
  17. package/dist/bridge/messages/connect.d.ts.map +1 -0
  18. package/dist/bridge/messages/{ready.js → connect.js} +14 -13
  19. package/dist/bridge/messages/hostToSandbox.d.ts +24 -79
  20. package/dist/bridge/messages/hostToSandbox.d.ts.map +1 -1
  21. package/dist/bridge/messages/hostToSandbox.js +2 -3
  22. package/dist/bridge/messages/init.d.ts +35 -6
  23. package/dist/bridge/messages/init.d.ts.map +1 -1
  24. package/dist/bridge/messages/init.js +8 -4
  25. package/dist/bridge/messages/initResult.d.ts +29 -0
  26. package/dist/bridge/messages/initResult.d.ts.map +1 -0
  27. package/dist/bridge/messages/initResult.js +25 -0
  28. package/dist/bridge/messages/queryDataSource.d.ts +3 -7
  29. package/dist/bridge/messages/queryDataSource.d.ts.map +1 -1
  30. package/dist/bridge/messages/queryDataSource.js +3 -7
  31. package/dist/bridge/messages/queryDataSourceResult.d.ts +4 -240
  32. package/dist/bridge/messages/queryDataSourceResult.d.ts.map +1 -1
  33. package/dist/bridge/messages/queryDataSourceResult.js +4 -22
  34. package/dist/bridge/messages/sandboxToHost.d.ts +21 -7
  35. package/dist/bridge/messages/sandboxToHost.d.ts.map +1 -1
  36. package/dist/bridge/messages/sandboxToHost.js +4 -2
  37. package/dist/bridge/sandboxClient.d.ts +2 -4
  38. package/dist/bridge/sandboxClient.d.ts.map +1 -1
  39. package/dist/bridge/sandboxClient.js +2 -5
  40. package/dist/customBlock.d.ts +1 -1
  41. package/dist/customBlock.d.ts.map +1 -1
  42. package/dist/customBlock.js +1 -1
  43. package/dist/host/createCustomBlockHost.d.ts +6 -3
  44. package/dist/host/createCustomBlockHost.d.ts.map +1 -1
  45. package/dist/host/createCustomBlockHost.js +227 -58
  46. package/dist/host/lifecycle/initErrors.d.ts +1 -1
  47. package/dist/host/lifecycle/initErrors.d.ts.map +1 -1
  48. package/dist/host/lifecycle/initErrors.js +25 -7
  49. package/dist/host/lifecycle/types.d.ts +6 -4
  50. package/dist/host/lifecycle/types.d.ts.map +1 -1
  51. package/dist/host/messages/invalidSandboxMessage.js +0 -3
  52. package/dist/host/queries/querySubscriptions.d.ts +10 -10
  53. package/dist/host/queries/querySubscriptions.d.ts.map +1 -1
  54. package/dist/host/queries/querySubscriptions.js +35 -19
  55. package/dist/host/queries/types.d.ts +5 -4
  56. package/dist/host/queries/types.d.ts.map +1 -1
  57. package/dist/host.d.ts +5 -3
  58. package/dist/host.d.ts.map +1 -1
  59. package/dist/host.js +2 -1
  60. package/dist/index.d.ts +2 -2
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +1 -1
  63. package/dist/init.d.ts +7 -7
  64. package/dist/init.d.ts.map +1 -1
  65. package/dist/init.js +70 -50
  66. package/dist/react/index.d.ts +1 -1
  67. package/dist/react/index.d.ts.map +1 -1
  68. package/dist/react/standalonePreview.d.ts.map +1 -1
  69. package/dist/react/standalonePreview.js +2 -0
  70. package/dist/react/useCustomBlockInit.d.ts +5 -6
  71. package/dist/react/useCustomBlockInit.d.ts.map +1 -1
  72. package/dist/react/useCustomBlockInit.js +3 -19
  73. package/dist/react/useRuntimeState.d.ts +4 -3
  74. package/dist/react/useRuntimeState.d.ts.map +1 -1
  75. package/dist/react/useRuntimeState.js +3 -2
  76. package/dist/version.js +1 -1
  77. package/docs/data-sources.md +7 -5
  78. package/docs/errors.md +5 -1
  79. package/docs/lifecycle.md +19 -31
  80. package/docs/manifest.md +1 -1
  81. package/package.json +1 -1
  82. package/src/bridge/SandboxBridge.ts +151 -77
  83. package/src/bridge/dataSources/resolve.ts +3 -14
  84. package/src/bridge/hostState.ts +3 -2
  85. package/src/bridge/loadManifest.ts +6 -6
  86. package/src/bridge/manifest.ts +3 -3
  87. package/src/bridge/messages/{ready.ts → connect.ts} +15 -14
  88. package/src/bridge/messages/hostToSandbox.ts +2 -6
  89. package/src/bridge/messages/init.ts +24 -10
  90. package/src/bridge/messages/initResult.ts +37 -0
  91. package/src/bridge/messages/queryDataSource.ts +3 -7
  92. package/src/bridge/messages/queryDataSourceResult.ts +4 -24
  93. package/src/bridge/messages/sandboxToHost.ts +4 -2
  94. package/src/bridge/sandboxClient.ts +3 -8
  95. package/src/customBlock.ts +2 -2
  96. package/src/host/createCustomBlockHost.ts +269 -64
  97. package/src/host/lifecycle/initErrors.ts +25 -7
  98. package/src/host/lifecycle/types.ts +13 -4
  99. package/src/host/messages/invalidSandboxMessage.ts +0 -3
  100. package/src/host/queries/querySubscriptions.ts +58 -39
  101. package/src/host/queries/types.ts +10 -11
  102. package/src/host.ts +13 -2
  103. package/src/index.ts +3 -1
  104. package/src/init.ts +73 -60
  105. package/src/react/index.ts +0 -1
  106. package/src/react/standalonePreview.ts +2 -0
  107. package/src/react/useCustomBlockInit.ts +6 -27
  108. package/src/react/useRuntimeState.ts +4 -3
  109. package/dist/bridge/messages/ready.d.ts.map +0 -1
package/HOST.md CHANGED
@@ -18,7 +18,7 @@ import {
18
18
 
19
19
  `readIncomingType()` is intentionally best-effort. Use it after validation fails so the host can avoid NACK loops and include a useful reason in `invalidSandboxMessage`.
20
20
 
21
- `createCustomBlockHost()` is an optional protocol loop for lightweight hosts. It owns iframe message listener setup, `ready` / `init`, protocol version checks, malformed-message NACKs, request routing, auto-resize callbacks, state-change messages, cleanup, and latest-query refresh bookkeeping. It deliberately does not know about any host's data model, permissions, iframe policy, analytics, or UI state.
21
+ `createCustomBlockHost()` is an optional protocol loop for lightweight hosts. It owns iframe message listener setup, `connect` / `init` / `initResult`, protocol version checks, malformed-message NACKs, request routing, auto-resize callbacks, state-change messages, cleanup, and latest-query refresh bookkeeping. It deliberately does not know about any host's data model, permissions, iframe policy, analytics, or UI state.
22
22
 
23
23
  ```ts
24
24
  import { createCustomBlockHost } from "@notionhq/custom-blocks/host";
@@ -31,52 +31,78 @@ const host = createCustomBlockHost({
31
31
  parent,
32
32
  page,
33
33
  currentUser,
34
+ manifest: persistedManifest,
34
35
  dataSources: { bindings },
35
36
  },
36
37
  handlers: {
37
- queryDataSource: async (message) => ({ items: [], hasMore: false }),
38
+ queryDataSource: async (message) => ({ status: "success", items: [], hasMore: false }),
38
39
  },
39
40
  });
40
41
  ```
41
42
 
42
43
  Use it when the generic protocol loop is helpful. Hosts with more specialized runtime needs can keep using the schemas and message types directly.
43
44
 
44
- Related types: `CustomBlockHostOptions`, `CustomBlockHostInitialState`, `CustomBlockHostInitialDataSources`, `CustomBlockHostDataSourcesPayload`, `CustomBlockHostHandlers`, `CustomBlockHostHandle`, `CustomBlockHostLogDirection`, `CustomBlockHostQueryDataSourceResult`, `CustomBlockHostCreatePageResult`, `CustomBlockHostGetPageResult`, `CustomBlockHostUpdatePageResult`, `CustomBlockHostGetUserResult`, and `CustomBlockHostListUsersResult`.
45
+ Related types: `CustomBlockHostOptions`, `CustomBlockHostInitialState`, `CustomBlockHostInitialDataSources`, `CustomBlockHostDataSourcesPayload`, `ConnectSuccessMessage`, `CustomBlockHostHandlers`, `CustomBlockHostHandle`, `CustomBlockHostLogDirection`, `CustomBlockHostQueryDataSourceResult`, `CustomBlockHostCreatePageResult`, `CustomBlockHostGetPageResult`, `CustomBlockHostUpdatePageResult`, `CustomBlockHostGetUserResult`, and `CustomBlockHostListUsersResult`.
45
46
 
46
47
  ## Bridge protocol
47
48
 
48
49
  ### Lifecycle
49
50
 
50
- The bridge is established with a handshake: the sandbox posts a `ready` when `initCustomBlock()` starts, and the host validates it and replies exactly once with `init`. Hosts should log and ignore duplicate `ready` messages instead of re-running the handshake. After that, narrower messages stream live state updates.
51
+ Initialization has three steps. A sandbox-generated `initializationId` identifies the handshake from start to finish. Ignore duplicate messages and messages carrying any other ID.
51
52
 
52
- The sandbox starts by sending `ready`. It declares the bridge protocol version, includes the custom blocks package semver as `sdkVersion` when available, and tells the host whether manifest discovery produced a usable manifest. Hosts should reject init when `ready` reports a manifest error, forwarding the sandbox's full error payload unchanged:
53
+ #### 1. Sandbox sends `connect`
53
54
 
54
- ```ts
55
- // sandbox → host
56
- { type: "ready", status: "success", bridgeProtocolVersion, sdkVersion, manifest: { /* custom_blocks.json */ } }
55
+ `connect` declares the bridge protocol version and SDK package version. A successful message may also include the manifest discovered in the sandbox:
57
56
 
58
- // sandbox → host, no manifest / no declared data requirements
59
- { type: "ready", status: "success", bridgeProtocolVersion, sdkVersion, manifest: null }
57
+ ```ts
58
+ // sandbox host without manifest
59
+ { type: "connect", initializationId, status: "success", bridgeProtocolVersion, sdkVersion }
60
60
 
61
- // sandbox → host, manifest failed to load or validate
62
- { type: "ready", status: "error", bridgeProtocolVersion, sdkVersion, error: { code: "manifest_invalid", message: "...", isRetryable: false } }
61
+ // sandbox → host with explicit manifest
62
+ { type: "connect", initializationId, status: "success", bridgeProtocolVersion, sdkVersion, manifest: { /* ... */ } }
63
63
  ```
64
64
 
65
- The host replies with exactly one `init`, which has two statuses. On success it carries the full initial state — `theme`, `blockId`, `parent`, `page`, `currentUser` (the `NotionUser` shape from the user result messages), and `dataSources: { bindings }`:
65
+ If `connect.status` is `"error"`, reply with `init.error` using the same `initializationId` and forward its complete error payload unchanged.
66
+
67
+ #### 2. Host sends `init`
68
+
69
+ The host sends exactly one `init` containing its authoritative manifest. It may
70
+ use the manifest from `connect` as input, but the manifest it returns may differ;
71
+ the sandbox applies the host's version.
72
+
73
+ `init.success` carries the chosen manifest together with the initial theme, block context, current user, and data-source bindings:
66
74
 
67
75
  ```ts
68
76
  // host → sandbox
69
- { type: "init", status: "success", theme, blockId, parent, page: { id, parent }, currentUser, dataSources: { bindings } }
77
+ { type: "init", initializationId, status: "success", theme, blockId, parent, page: { id, parent }, currentUser, manifest, dataSources: { bindings } }
70
78
  ```
71
79
 
72
- On failure it carries `error: { code, message, isRetryable }` (`CustomBlockInitErrorInfo` / `customBlockInitErrorInfoSchema`, with `code` drawn from `CustomBlockInitErrorCode` / `customBlockInitErrorCodeSchema`). The SDK surfaces this as a `CustomBlockInitError`:
80
+ If the host cannot initialize the block, send `init.error` instead:
73
81
 
74
82
  ```ts
75
83
  // host → sandbox
76
- { type: "init", status: "error", error: { code: "context_unavailable", message: "...", isRetryable: true } }
84
+ { type: "init", initializationId, status: "error", error: { code: "context_unavailable", message: "...", isRetryable: true } }
85
+ ```
86
+
87
+ Use `CustomBlockInitErrorCode` / `CustomBlockInitErrorInfo` to construct this error and `customBlockInitErrorCodeSchema` / `customBlockInitErrorInfoSchema` to validate it. `init.error` is terminal; the sandbox does not reply with `initResult`.
88
+
89
+ #### 3. Sandbox sends `initResult`
90
+
91
+ After applying `init.success`, the sandbox acknowledges whether it accepted the manifest and bindings:
92
+
93
+ ```ts
94
+ // sandbox → host
95
+ { type: "initResult", initializationId, status: "success" }
96
+
97
+ // sandbox → host, host supplied bindings the SDK could not apply
98
+ { type: "initResult", initializationId, status: "error", error: { code: "invalid_init_bindings", message: "...", isRetryable: false } }
77
99
  ```
78
100
 
79
- After `init`, narrower messages update live state without re-running the handshake — `themeChanged`, `parentChanged`, `pageChanged`, `currentUserChanged`, and `dataSourcesChanged`. Each replaces just its slice of state:
101
+ Use `CustomBlockInitResultErrorCode` / `CustomBlockInitResultErrorInfo` to construct this error and `customBlockInitResultErrorCodeSchema` / `customBlockInitResultErrorInfoSchema` to validate it.
102
+
103
+ Wait for `initResult.success` before uncovering the iframe or sending live updates. `initResult.error` is terminal.
104
+
105
+ After `initResult.success`, narrower messages update live state without re-running the handshake — `themeChanged`, `parentChanged`, `pageChanged`, `currentUserChanged`, and `dataSourcesChanged`. Each replaces just its slice of state:
80
106
 
81
107
  ```ts
82
108
  // host → sandbox, any time after init
@@ -88,13 +114,17 @@ After `init`, narrower messages update live state without re-running the handsha
88
114
 
89
115
  ### Versioning
90
116
 
91
- `ready` includes `bridgeProtocolVersion` (the host <-> sandbox version) and `sdkVersion` (the package semver). Hosts should reject or fail `init` when the sandbox reports a `bridgeProtocolVersion` the host does not implement, but should treat `sdkVersion` as purely analytics metadata.
117
+ `connect` includes `bridgeProtocolVersion` (the host <-> sandbox version) and `sdkVersion` (the package semver). Hosts should reject or fail `init` when the sandbox reports a `bridgeProtocolVersion` the host does not implement, but should treat `sdkVersion` as purely analytics metadata.
92
118
 
93
119
  If the sandbox reports a version below the host's supported minimum, reply with `init.status: "error"` and `error.code: "unsupported_protocol_version"`. If the reported version is structurally invalid (not a positive integer — e.g. `0`, negative, fractional, `NaN`, or `Infinity`), reply with `error.code: "invalid_protocol_version"` instead.
94
120
 
95
121
  ### Conventions
96
122
 
97
- Every request/response pair uses a string `requestId`. The sender tracks pending requests by id; the receiver echoes the id on the matching result. The sandbox drops stale results that no longer match the latest outstanding request for that operation.
123
+ One-shot RPC request/result pairs use a string `requestId`. The sender tracks pending requests by id, and the receiver echoes the id on the matching result. Lifecycle and one-way messages use neither request nor subscription identity.
124
+
125
+ `queryDataSource` is a long-lived subscription rather than a one-shot RPC. It and every `queryDataSourceResult` update use only a stable string `subscriptionId`. The host may push additional results for that subscription whenever its data changes; the sandbox ignores results for subscriptions it no longer recognizes.
126
+
127
+ Hosts key query state by `subscriptionId`, not `dataSourceId`: multiple subscriptions may target the same data source, and a data-source refresh must update all of them. A new request with an existing `subscriptionId` replaces that subscription, so hosts must suppress an older handler result that resolves after the replacement. Subscription lifetime ends when the host/bridge is torn down; protocol v3 has no unsubscribe message.
98
128
 
99
129
  Both sides validate inbound messages with valibot schemas. Failed parses are logged and NACKed with `invalidHostMessage` or `invalidSandboxMessage`. Never answer a NACK with another NACK.
100
130
 
@@ -108,7 +138,7 @@ Hosts should emit the most specific stable code available. Unexpected or unclass
108
138
 
109
139
  Host implementers can use the API-specific aliases and schemas when shaping outbound failures: `CustomBlockCreatePageErrorCode` / `CustomBlockCreatePageErrorInfo` / `customBlockCreatePageErrorCodeSchema` / `customBlockCreatePageErrorInfoSchema`, `CustomBlockGetPageErrorCode` / `CustomBlockGetPageErrorInfo` / `customBlockGetPageErrorCodeSchema` / `customBlockGetPageErrorInfoSchema`, `CustomBlockGetUserErrorCode` / `CustomBlockGetUserErrorInfo` / `customBlockGetUserErrorCodeSchema` / `customBlockGetUserErrorInfoSchema`, `CustomBlockListUsersErrorCode` / `CustomBlockListUsersErrorInfo` / `customBlockListUsersErrorCodeSchema` / `customBlockListUsersErrorInfoSchema`, `CustomBlockQueryDataSourceErrorCode` / `CustomBlockQueryDataSourceErrorInfo` / `customBlockQueryDataSourceErrorCodeSchema` / `customBlockQueryDataSourceErrorInfoSchema`, and `CustomBlockUpdatePageErrorCode` / `CustomBlockUpdatePageErrorInfo` / `customBlockUpdatePageErrorCodeSchema` / `customBlockUpdatePageErrorInfoSchema`. Shared categories are exported as `CustomBlockPropertyErrorCode` / `CustomBlockPropertyErrorInfo` / `customBlockPropertyErrorCodeSchema` and `CustomBlockDataSourceResolutionErrorCode` / `CustomBlockDataSourceResolutionErrorInfo` / `customBlockDataSourceResolutionErrorCodeSchema`. The broad fallback schema remains `customBlockErrorInfoSchema`.
110
140
 
111
- `queryDataSource` carries the resolved raw `dataSourceId` and a sandbox-generated `snapshotId`; semantic data-source keys never cross the bridge for queries. `createPage` arrives with `parent` already resolved to `page_id` or `data_source_id`.
141
+ `queryDataSource` carries the resolved raw `dataSourceId` and a sandbox-generated `subscriptionId`; semantic data-source keys never cross the bridge for queries. `createPage` arrives with `parent` already resolved to `page_id` or `data_source_id`.
112
142
 
113
143
  ## Data sources
114
144
 
@@ -138,9 +168,10 @@ Messages sent from the sandbox to the host. Parse `window` `message` events with
138
168
 
139
169
  | Wire type | Type / schema | Behavior |
140
170
  | -------------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
141
- | `ready` | `ReadyMessage` / `readyMessageSchema` | One-shot handshake; carries `bridgeProtocolVersion`, `sdkVersion`, and the manifest. |
142
- | `queryDataSource` | `QueryDataSourceMessage` / `queryDataSourceMessageSchema` | `requestId`-keyed request for the current rows in a raw `dataSourceId`. `snapshotId` names the SDK result slot to update, so later refreshes for the same `useDataSource` call replace the same snapshot instead of creating a new one. |
143
- | `createPage` | `CreatePageMessage` / `createPageMessageSchema` | `requestId`-keyed page creation with properties and optional position; parent is `page_id` or `data_source_id`. Create-time icon and cover are not supported. |
171
+ | `connect` | `ConnectMessage` / `connectMessageSchema` | Starts the one-shot handshake with a sandbox-generated `initializationId`; carries `bridgeProtocolVersion`, `sdkVersion`, and the manifest. |
172
+ | `initResult` | `InitResultMessage` / `initResultMessageSchema` | Echoes the handshake `initializationId` and reports whether the sandbox applied `init.success`. |
173
+ | `queryDataSource` | `QueryDataSourceMessage` / `queryDataSourceMessageSchema` | Starts or updates a `subscriptionId`-keyed subscription for rows in a raw `dataSourceId`. Later results for the same subscription replace its current value. |
174
+ | `createPage` | `CreatePageMessage` / `createPageMessageSchema` | `requestId`-keyed page creation with properties and optional position; parent is `page_id` or `data_source_id`. Create-time icon and cover are not supported. |
144
175
  | `getPage` | `GetPageMessage` / `getPageMessageSchema` | `requestId`-keyed page fetch by page id. |
145
176
  | `updatePage` | `UpdatePageMessage` / `updatePageMessageSchema` | `requestId`-keyed patch (properties, icon, cover, or `archived`). |
146
177
  | `getUser` | `GetUserMessage` / `getUserMessageSchema` | `requestId`-keyed user fetch by user id. |
@@ -154,20 +185,20 @@ Messages sent from the sandbox to the host. Parse `window` `message` events with
154
185
 
155
186
  Messages sent from the host to the sandbox. Same `{ wire type, type / schema, behavior }` shape; the type / schema column points to the payload shape.
156
187
 
157
- | Wire type | Type / schema | Behavior |
158
- | ----------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- |
159
- | `init` | `InitMessage` / `initMessageSchema` | Sent exactly once in response to `ready`; carries the success/error payload described under [Lifecycle](#lifecycle). |
160
- | `themeChanged` | `ThemeChangedMessage` / `themeChangedMessageSchema` | Replaces the current theme. |
161
- | `parentChanged` | `ParentChangedMessage` / `parentChangedMessageSchema` | Replaces the custom block parent without disturbing theme, block ID, page ID, user, or query state. |
162
- | `pageChanged` | `PageChangedMessage` / `pageChangedMessageSchema` | Replaces the nearest page ancestor without disturbing theme, block ID, parent, user, or query state. |
163
- | `currentUserChanged` | `CurrentUserChangedMessage` / `currentUserChangedMessageSchema` | Replaces the current viewer record. Send when any viewer field changes (name, avatar, email). |
164
- | `dataSourcesChanged` | `DataSourcesChangedMessage` / `dataSourcesChangedMessageSchema` | Replaces data-source bindings; the sandbox preserves cached query state for keys that still exist and drops removed keys. |
165
- | `queryDataSourceResult` | `QueryDataSourceResultMessage` / `queryDataSourceResultMessageSchema` | `requestId` / `snapshotId`-keyed response with `status: "success"`, `items`, and `hasMore`, or `status: "error"` and `error`. |
166
- | `createPageResult` | `CreatePageResultMessage` / `createPageResultMessageSchema` | `requestId`-keyed page response with `status: "success"` or `status: "error"`. |
167
- | `getPageResult` | `GetPageResultMessage` / `getPageResultMessageSchema` | Same success/error shape as `createPageResult`. |
168
- | `updatePageResult` | `UpdatePageResultMessage` / `updatePageResultMessageSchema` | Same success/error shape as `createPageResult`. |
169
- | `getUserResult` | `GetUserResultMessage` / `getUserResultMessageSchema` | `requestId`-keyed user response with `status: "success"` or `status: "error"`. |
170
- | `listUsersResult` | `ListUsersResultMessage` / `listUsersResultMessageSchema` | Same success/error shape as `getUserResult`. |
188
+ | Wire type | Type / schema | Behavior |
189
+ | ----------------------- | --------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
190
+ | `init` | `InitMessage` / `initMessageSchema` | Sent exactly once in response to `connect`; echoes its `initializationId` and carries the success/error payload described under [Lifecycle](#lifecycle). |
191
+ | `themeChanged` | `ThemeChangedMessage` / `themeChangedMessageSchema` | Replaces the current theme. |
192
+ | `parentChanged` | `ParentChangedMessage` / `parentChangedMessageSchema` | Replaces the custom block parent without disturbing theme, block ID, page ID, user, or query state. |
193
+ | `pageChanged` | `PageChangedMessage` / `pageChangedMessageSchema` | Replaces the nearest page ancestor without disturbing theme, block ID, parent, user, or query state. |
194
+ | `currentUserChanged` | `CurrentUserChangedMessage` / `currentUserChangedMessageSchema` | Replaces the current viewer record. Send when any viewer field changes (name, avatar, email). |
195
+ | `dataSourcesChanged` | `DataSourcesChangedMessage` / `dataSourcesChangedMessageSchema` | Replaces data-source bindings; the sandbox preserves cached query state for keys that still exist and drops removed keys. |
196
+ | `queryDataSourceResult` | `QueryDataSourceResultMessage` / `queryDataSourceResultMessageSchema` | `subscriptionId`-keyed update with `status: "success"`, `items`, and `hasMore`, or `status: "error"` and `error`. |
197
+ | `createPageResult` | `CreatePageResultMessage` / `createPageResultMessageSchema` | `requestId`-keyed page response with `status: "success"` or `status: "error"`. |
198
+ | `getPageResult` | `GetPageResultMessage` / `getPageResultMessageSchema` | Same success/error shape as `createPageResult`. |
199
+ | `updatePageResult` | `UpdatePageResultMessage` / `updatePageResultMessageSchema` | Same success/error shape as `createPageResult`. |
200
+ | `getUserResult` | `GetUserResultMessage` / `getUserResultMessageSchema` | `requestId`-keyed user response with `status: "success"` or `status: "error"`. |
201
+ | `listUsersResult` | `ListUsersResultMessage` / `listUsersResultMessageSchema` | Same success/error shape as `getUserResult`. |
171
202
  | `invalidSandboxMessage` | `InvalidSandboxMessage` / `invalidSandboxMessageSchema` | Host-side NACK for a sandbox message it could not parse. |
172
203
 
173
204
  `HostToSandboxMessage` / `hostToSandboxMessageSchema` is the discriminated union over all of the above.
@@ -2,9 +2,9 @@ import * as v from "valibot";
2
2
  import { notionPropertyTypeSchema } from "./dataSources/propertySchema.js";
3
3
  /**
4
4
  * User-authored manifest declaring the data sources the custom block expects.
5
- * Lives at `custom_blocks.json` in the project root and is forwarded to the host with
6
- * the bridge `ready` message so the host can pre-bind data sources, surface
7
- * configuration UI, etc. The `notionCustomBlock` Vite plugin from
5
+ * Lives at `custom_blocks.json` in the project root. The sandbox may send it in
6
+ * `connect`, and the host returns the authoritative manifest in `init`. The
7
+ * `notionCustomBlock` Vite plugin from
8
8
  * `@notionhq/custom-blocks/vite` wires the JSON file into the dev server and
9
9
  * the build output.
10
10
  */
@@ -3,7 +3,6 @@ import type { NotionDataSource } from "./dataSources/dataSource.js";
3
3
  import type { NotionDataSourcePageUpdateInput, NotionDataSourcePageUpdateResult } from "./dataSources/dataSourcePage.js";
4
4
  import { type CustomBlockHostState } from "./hostState.js";
5
5
  import type { ManifestLoadResult } from "./loadManifest.js";
6
- import type { CustomBlockManifest } from "./manifest.js";
7
6
  import { type InitMessage } from "./messages/init.js";
8
7
  /**
9
8
  * Used to ensure that the host and client are using the same version of the bridge protocol. A
@@ -31,31 +30,26 @@ export declare class SandboxBridge {
31
30
  private readonly pendingGetUser;
32
31
  private readonly pendingListUsers;
33
32
  private readonly pendingUpdatePage;
34
- private hasSentReady;
33
+ private hasSentConnect;
34
+ private hasReceivedInit;
35
+ private initializationId;
35
36
  private latestDataSourceBindings;
37
+ private isMockState;
36
38
  private resolveInit;
37
39
  private rejectInit;
38
40
  private readonly initMessage;
39
- private manifest;
40
41
  constructor();
41
42
  private static MAX_LOG_ENTRIES;
42
43
  private logMessage;
43
44
  getMessageLog(): readonly MessageLogEntry[];
44
45
  subscribeToMessageLog(listener: () => void): () => boolean;
45
- awaitInit(signal?: AbortSignal): Promise<InitMessage>;
46
- sendReady(manifestResult: ManifestLoadResult): void;
46
+ awaitInit(signal?: AbortSignal): Promise<void>;
47
+ sendConnect(manifestResult: ManifestLoadResult): void;
47
48
  private postToHost;
48
49
  private notify;
49
50
  private handleMessage;
50
51
  subscribe(listener: () => void): () => boolean;
51
52
  getHostState(): CustomBlockHostState;
52
- /**
53
- * The author-declared manifest loaded from `custom_blocks.json` and forwarded
54
- * to the host in `ready`. `null` when it failed to load/parse and the host
55
- * should reject init via `ready.status: "error"`. Static for the lifetime
56
- * of the sandbox.
57
- */
58
- getManifest(): CustomBlockManifest | null;
59
53
  /**
60
54
  * Apply an `init` payload as if it had arrived from the host. Lets callers
61
55
  * seed the bridge directly (e.g. the React provider's standalone preview
@@ -1 +1 @@
1
- {"version":3,"file":"SandboxBridge.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/SandboxBridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SandboxBridge.d.ts","sourceRoot":"","sources":["../../../../home/runner/work/custom-blocks/custom-blocks/sdk/src/bridge/SandboxBridge.ts"],"names":[],"mappings":"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"}